Authorization API signs JWTs as RS256 when HS256 is selected

I’m having trouble with Auth0’s Authorization API, specifically logging in with a token using the /oauth/token endpoint and “password” grant type. When I request a token, the server responds with a JWT that’s signed with RS256 instead of HS256. I’ve already ensured that the JWT signature algorithm in my client’s settings is set to HS256.

![alt text][1]

Here’s an example of the request I’m making:

POST https://foo.auth0.com/oauth/token
{  "grant_type": "password",
  "username": "foo@bar.com",
  "password": "secret",
  "scope":"openid email",
  "client_id": "id_goes_here" }

Yet the server responds with the following token:

{  "typ": "JWT",
  "alg": "RS256",
  "kid": "QjJFRTZDRUNEO... }

The /oauth/token endpoint is part of the authentication API surface that makes the new OIDC compliant flows. In this mode, ID tokens issued to public client are forcibly signed with RS256 instead of HS256. The reason is that a public client is unable to securely maintain the client secret needed to validate a HS256 token and as such requires the usage of RS256.

For reference information on the differences between /oauth/token and it’s legacy counterpart /oauth/ro you can check this docs page.

So @jmangelo is there any way to force that endpoint to return tokens with HS256 signatures? Because we are having this problem - our API’s is configured to use HS256 tokens, and our iOS client tries to get token from that new shiny endpoint, and the result is bad. So we either have to force iOS use the old /oauth/ro, or implement breaking changes to our API’s.
Side note, from UI point of view, that switch there tells nothing that selected algorithm is not going to be applied to your tokens, neither do the API docs, and a result comes as a surprise.

1 Like

So @jmangelo is there any way to force that endpoint to return tokens with HS256 signatures? Because we are having this problem - our API’s is configured to use HS256 tokens, and our iOS client tries to get token from that new shiny endpoint, and the result is bad. So we either have to force iOS use the old /oauth/ro, or implement breaking changes to our API’s.
Side note, from UI point of view, that switch there tells nothing that selected algorithm is not going to be applied to your tokens, neither do the API docs, and a result comes as a surprise.

The constraint is meant for ID tokens issued to public clients; if you have a client application and an API you should treat them separately and configure the API in the APIs section of the dashboard. This would allow you to choose HS256 for the signing algo of the access tokens issued. The client application would then need to obtain access tokens meant for the API in question and use them instead of sending ID tokens. Currently, an access token issued to an API uses the JWT format so it would reduce the need for changes in the API side of it. See: Authentication and Authorization Flows

I do believe that /oauth/token does indeed support HS256.

This endpoint requires a “client_secret” parameter in the payload if the client is configured for HS256 and OIDC unsupported.

RS256 does not require the client secret

https://auth0.com/docs/api/authentication#client-credentials

As a proof of concept I performed the following steps:

Auth0 Client Configuration:
Auth0 → Clients → [client] → Settings → Advanced Settings:
JsonWebToken Signature Algorithm : HS256
OIDC Conformant : unchecked

curl --request POST \
  --url 'https://[DOMAIN]/oauth/token' \
  --header 'content-type: application/json' \
  --data  '{"grant_type":"http:\/\/auth0.com\/oauth\/grant-type\/password-realm","client_id":"[CLIENTID]", "client_secret":"[CLIENT SECRET]", "realm":"Username-Password-Authentication", "scope":"openid","username":"[USERNAME]","password":"[PASSWORD]"}'

Make sure your client settings has Token Endpoint Authentication Method set to Post if you’re using Regular Web Application.

The description of that field: Defines the requested authentication method for the token endpoint. Possible values are ‘None’ (public client without a client secret), ‘Post’ (client uses HTTP POST parameters) or ‘Basic’ (client uses HTTP Basic).