The RFC recommends to use PKCE for web (public client)/native apps. It’s not stated that Dynamic Client Registration (DCR) is bad but it’s not stated as an alternative either. I am wondering if there is any negative aspect of the DCR that i am overlooking.
I would say that the biggest difference between the two is the fact that PKCE is much easier to implement with less bookkeeping while offering about the same protections as DCR.
Looking through the use cases defined in the DCR specification, it looks like the use case of native app or SPA app is included.
Is there a reason why is not included in the best practices? Which use case is ideal to use the DCR?
As per the RFC7636 it stops malicious apps which pretend to be legitimate apps, gaining access to OAuth2.0 protected API’s.
The flow suggests a method of having a runtime level secret which generated from the client and letting the Auth server knows it. This allows token issuer to verify the secret with auth server and grant a proper access token.
However lets assume a malicous app, as the RFC paper suggests, with a correct client_id and client_secret, it can do the same PKCE process and gain access to protected resources.
Is this RFC doesn’t meant to protect those kind of attacks or simply I’m missing something here?
As answered in this question, Single Page Applications shouldn’t be given a refresh token with the OIDC Authorization Code Flow.
Can you indicate some way of getting a new access token when it expires (without interrupting the SPA UX state (no redirects…)?
If the use refresh tokens were the only solutions, what are the ways we can minimize the risk of leakeage? E.g: is storing it in the browser’s session storage safe enough? Do IdPs provide a some form of refresh_token expiration, etc.
I’ve run into this docs when I was studying some SSO concepts;
This grant adds the concept of a code_verifier to the Authorization Code Grant. When the Client asks for an Authorization Code it generates a code_verifier and its transformed value called code_challenge. The code_challenge and a code_challenge_method are sent along with the request. When the Client wants to exchange the Authorization Code for an Access Token, it also sends along the code_verifier. The Authorization Server transforms this and if it matches the originally sent code_challenge, it returns an Access Token.
And here is the flow;
The part that I did not quite get is how the PKCE way is secure as the interceptor still be able to intercept the
code_verifier as much as he could intercept the
auth code. I believe I’m missing a point but not able to figure out what it is.
The Oauth PKCE protocol flow is as follows, as defined in RFC 7636:
+-------------------+ | Authz Server | +--------+ | +---------------+ | | |--(A)- Authorization Request ---->| | | | | + t(code_verifier), t_m | | Authorization | | | | | | Endpoint | | | |<-(B)---- Authorization Code -----| | | | | | +---------------+ | | Client | | | | | | +---------------+ | | |--(C)-- Access Token Request ---->| | | | | + code_verifier | | Token | | | | | | Endpoint | | | |<-(D)------ Access Token ---------| | | +--------+ | +---------------+ | +-------------------+
My question is: why do we need to use a trapdoor like
S256 in step (A)?
According to the RFC’s threat model, a malicious app cannot intercept the outgoing communication in (A) or (C). So why can’t an app generate and temporarily store a random value in (A) and re-use it in (C)?
To elaborate: the goal of
S256(code_verifier)) is to later enable the app to prove to the server that it is indeed the app as it possess
code_verifier before the transform.
However, if the app just sent
code_verifier and later sent it again, the same guarantee is achieved: the server receives a random value that uniquely identifies the app, and receives it again. No other app can provide this value: as long as the connection isn’t intercepted (and it shouldn’t be – TLS),
S256 seems unnecessary.
I am considering moving my SPA from Implicit flow to Authorization Code + PKCE extension.
This new flow will provide the SPA with a Refresh Token that doesn’t expire.
Let’s say a malicious user on the computer/browser manages to get hold of the Refresh Token from the browser.
What are the remediations I need to set-up on the IdP and other systems to impersonate my SPA and indefinitely exchange the Refresh token for a new pair of Access Token and Refresh Token?
I’ve looked around and have found no clear explanation on this matter.
Why even have a redirect? Wouldn’t just a normal TLS/HTTPS request/response protect the requests and token?
The one argument I have heard against TLS is that there could be an app that acts as a proxy and presents it’s one cert on the phone. But if that is the case how would this be different from a normal desktop app?
To me it seems like PKCE is protecting against a compromised device. I would assume if native requires PKCE then desktop apps (non-browser) would also require PKCE.
In attempting to implement OAuth2 into a natively installed client application, we face the problem that we cannot securely store the pre-shared client secret. After doing some research, I came across PKCE, which I had not previously heard of. Swapping out the client secret for a short-lived nonce seems like a reasonable idea to me, but I can’t figure out how we protect against what seems like a fairly clear man-in-the-middle attack. My thinking is thus:
The flow starts with Alice sending bob a hashed code challenge along with some assertion of her identity (like a session token). The challenge is hashed because it cannot be assumed to be secure. The server stores the hashed code challenge but otherwise follows basic OAuth2 and returns an authorisation code. All good so far.
The next step is for Alice to send the authorisation code and the now un-hashed code challenge back to Bob, now all encrypted in an HTTPS POST request. Bob can validate the code challenge by hashing the value and comparing it with the previous hash, and generate an access token for the authorisation code.
I understand that the reason this is “more secure” is because an interceptor (“Eve”) would not have the plain text code challenge value in the second step, and thus, even if they heard the authorisation code, wouldn’t be able to request an access token. My concern is, though, could Eve not just intercept the initial request and swap out the hashed code challenge for the hash of challenge she created herself? Then the authorisation code would be associated with that challenge and not Alice’s!
I’ve gone round this a few times and flip flopped between being happy I’ve understood it and not convinced, so it’s probably a case I’ve thought about this too much. But if someone could explain why I am wrong in plain English I would much appreciate it 🙂
Thanks in advance!