I am building 2 apps; a front-end, and a back-end.
The back-end will be built using Rails API + Doorkeeper Gem (oauth2 provider) while the front-end will be built using React Native.
Currently, I am using "Client Credentials Grant Flow" which works just fine at the moment. But after researching for a while, this flow shouldn't be used in a client-only app as it exposes the client_secret
if ever someone decompiles the app.
I have also read about "Implicit Grant Flow" which only requires client_id
. But this flow seems old now?
And according to this: https://auth0.com/docs/api-auth/which-oauth-flow-to-use#is-the-client-a-single-page-app-
It is recommending to use "Authorization Code Grant with PKCE" over "Implicit Grant Flow". I am able to make it work but the problem is that it still needs the client_secret
in order to get an access_token
, is this how it should be?
Here is the sample flow I am doing:
curl -X POST 'http://localhost:3000/oauth/authorize?client_id=xxxx&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=public&code_challenge=testchallenge&code_challenge_method=plain'
This will give me the following response:
{
"status": "redirect",
"redirect_uri": {
"action": "show",
"code": "8quZ-EAiKKG2EKnQiSYs3xeFRCgsIwcTbaWNdjnpyFg"
}
}
And then I will use the code above to get an access token using the request below:
curl -i http://localhost:3000/oauth/token \
-F grant_type="authorization_code" \
-F client_id="xxxx" \
-F client_secret="xxxx" \
-F code="8quZ-EAiKKG2EKnQiSYs3xeFRCgsIwcTbaWNdjnpyFg" \
-F redirect_uri="urn:ietf:wg:oauth:2.0:oob" \
-F code_verifier="testchallenge"
Now here is the problem, in order to exchange code
to an access_token
I will still be needing the client_secret
. How is it different from "Client Credentials Grant Flow" if both will just expose my client_secret
?
The above command will return the following:
{
"access_token": "nQoorBqLxQH4qFpmlx3mGG6Cd_TfX4d3L3gAGOTwrFs",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "public",
"created_at": 1595517643
}
If I don't include the client_secret
in the request here is the response:
{
"error": "invalid_client",
"error_description": "Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."
}
So here are my questions:
client_secret
to get access_token
on PKCE flow?client_secret
?client_secret
?Doorkeeper PKCE documentation: https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-PKCE-flow
It depends. Originally PKCE was introduced to protect public clients (a client which cannot protect a secret). But recently, with practices, PKCE became a recommendation for authorization code grant (source)
2.1.1. Authorization Code Grant
Clients MUST prevent injection (replay) of authorization codes into
the authorization response by attackers. The use of PKCE [RFC7636]
is RECOMMENDED to this end. The OpenID Connect "nonce" parameter and ID Token Claim [OpenID] MAY be used as well. The PKCE challenge or
OpenID Connect "nonce" MUST be transaction-specific and securely
bound to the client and the user agent in which the transaction was
started.Note: although PKCE so far was designed as a mechanism to protect
native apps, this advice applies to all kinds of OAuth clients,
including web applications.
In short, to avoid authorization code replay attacks (spec - introduction). And this happens inside end user's device and not in the transmission of data. TLS is mandatory for OAuth 2.0 token request.
No grant will expose credentials as token requests are done via TLS.
I think in your case, the client is a confidential client (spec - client types). So I would recommend to check this aspect in authorization server.