code_challange vs state parameter in OAuth? What is the difference? - oauth-2.0

I'm trying to understand the difference between code_challange and state parameter from OAuth 2.0 Authorization Code Flow + PKCE.
I know that state parameter is a validation against CSRF attack and is generated (and saved in local storage) on Client (eg. Angular SPA) - and need to be returned from Authorization application in callback after successful login and compared with state value saved previously on local storage.
Whereas code_challange is generated based on code_verifier also genereated and saved in localstorage. So where is the differance with usage?
Also I've noted strange thing - I copied generated auth url which is: https://APP_ADDRESS.b2clogin.com/APP_ADDRESS.onmicrosoft.com/b2c_signupsignin/oauth2/v2.0/authorize?client_id=f9d2b[...]&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fauth-callback&response_type=code&scope=f9d2b[...]%20openid&state=31caa207[...]&code_challenge=-MefGRhOo[...]&code_challenge_method=S256&response_mode=query
And I used that url in different browser. And I was able to login successfuly. I only had an error in console: No matching state found in storage. Which make sense since local storage was empty in new browser.
But why there wasn't any error about the code_challange? I think it shouldn't be able to login successful, or I miss something?

With PKCE, the checks that the code_challenge is correct is done on the authentication server-side and the check for valid state is done on the client-side.
There are cases where the client does not check the state/nonce properly (or not at all) and we added PKCE to let the auth-server do the check instead. The auth server can force/require that all clients follow the PKCE concept.
Together we get a very strong protection.
The picture below shows how PKCE works

Related

Oauth2 authorization code flow: where do I store authorization code?

Good day! I am trying to implement my own authorization server using oauth2 standards. Upon reading into its specifications on authorization code flow, a 3rd party application requesting for API access needs an authorization code from the authorization server, which will then be used to exchange for an access token. My question is, once I generate an authorization code from my authorization server, by concept, where do I store it so that when a client app requests an exchange for access token, I can verify that the authorization code is valid?
You can store the code anywhere you want - in your server memory (as an object in a map), in a database or in any other safe storage. If your server is just a single application (having just one RAM), you can store the codes in memory if you don't mind losing them during application restarts. But if you want to run multiple instances of your application (e.g. in Kubernetes) or server is composed of multiple applications, you will need to use some external storage (database, Hazelcast, Redis).
With the code, you will need to keep metadata such as client_id, validity, PKCE attributes (code_challenge_method, code_challenge) and such. When you receive a request to your token endpoint wanting to exchange the code for tokens, you need to find the code in your storage, compare the relevant metadata (client_id, PKCE code_verifier, client_secret) and issue tokens.
But you should keep the code with a timestamp saying when the tokens were issued. And you should be able to find what tokens were issued from the code. Because if you receive another /token exchange request with the same code, you should invalidate all the tokens issued - the code was probably stolen.
It's good to read OAuth2 Security RFC for all the considerations.
You can create a global data structure map and map the client_id to the auth codes and delete them after the access token is exchanged, this is a very simple a valid solution as long as it is properly implemented and the auth code and deleted correctly.
Since the exchange happens directly, you don't need to worry about the heap filling up since the auth code is created and deleted in a very short period of time making space. Say 1000 users log in every minute, a data structure of 1000 elements is very acceptable in most cases assuming there is a timeout of the exchange of 1 min (which should be the case)

Best practice on Securing code_verifier in PKCE-enhanced Authorization Code Flow

Since PKCE is now the recommended method of authorisation over the implicit flow, i'm looking for best practice on handling code verifier and recommendations on how this might be done. On high level PKCE Authorisation flow consist of:
Generate code_verifier on client side
Generate code_challenge from (1)
hit /authorise with code_challenge which redirect to select idp and in callback there's a code
use code from (3) along with code_verifier to exchange for access token
Question is, in step 3, before the application redirect to authorisation server and then the idp, one has to store the code_verifier somewhere. Where is that somewhere?
Seems like libraries like okta-oidc-js store the code_verifier in sessionStorage. Doesn't that expose you to XSS attack? i.e. if i was store the code_verifier in sessionStorage before the application goes into the Authorisation flow and redirects, on the callback, what stops some rouge extension from reading the code from the url and code_verifier from sessionStorage? Combination of which can be used to exchange for a access token.
What you describe is the standard SPA way of doing things - it could potentially be abused by malicious code, but there is some protection in the fact that an authorization code can only be used once and that the verifier is not stored for long.
A related XSS attack is to run a complete OAuth authorization redirect + code exchange on a hidden iframe - there is no protection against that, regardless of whether a back end or client secret is involved.
If you want to be strict about security, the emerging trend is more of a back end for front end approach, where the back end is a 'Proxy API' running at https://api.mywebdomain.com
The result of OAuth authorization is a same site cookie issued by the API, to prevent the above iframe attack
The SPA can then either use the auth cookie to get an access token or double hop API requests via the proxy API.
There is a good recent video on SPA security here that discusses these threats in further depth. The browser is a difficult place to implement security and redirects come with risks.
It is still recommended to separate Web and API concerns however - eg the above proxy API should not get in the way of a company wanting to deploy their SPA via a content delivery network.
LOGIN DANCE
In my opinion the preferred approach is summarized below, for full control and no issues with recent browser changes:
SPA calls a URL such as https://api.mywebdomain.com/login/start, which writes an HTTP only encrypted cookie for .mywebdomain.com containing the state and code_verifier, and also returns the authorization request URL
SPA then does the redirect itself, and saves page location / state to session storage beforehand if needed
SPA then receives the response URL with code and state, then POSTs them to a URL such as https://api.mywebdomain.com/login/end. Afterwards the SPA can restore its page location and state, so that usability is good.
API completes the login by verifying the state against that in the state cookie, then using the code_verifier from the state cookie. The result of all of this is to write an auth cookie (containing a refresh token) that could not be abused on an iframe.
I agree with Gary's approach, with one change.
The response url with code and state does not need to be intercepted by SPA and converted into another POST call to the BFF (backend for frontend).
If secure cookies were set on the browser at the beginning of the flow containing state and code verifier, the response url can land directly on the BFF which will then have all the parameters available for performing the code exchange (state and code as url parameters, code_verifier from cookie)

How to manage `state` nonce auth0 authorization code grant flow?

My application consists of a client side html/javascript, a web server, and an API (a "regular web app", as auth0 calls it). On the Authorization Code Grant doc page on Auth0, it says to create a URL like this:
https://ygctest.auth0.com/authorize?
audience=YOUR_API_AUDIENCE&
scope=YOUR_SCOPE&
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://YOUR_APP/callback&
state=YOUR_OPAQUE_VALUE
The doc says the state (apparently a nonce to prevent CSRF) returned from the auth0 server via query parameter to /callback needs to be compared to the originally generated state.
My question is: Where should the "state" variable be generated? And, does the state variable need to be verified on the client, server, or both?
Should I generate it on the server and pass it to the client somehow? If so, is it better to do it as a cookie, or can I just generate the entire URL serverside and stick it in the html?
If the state variable should be generated on the client side, how should the server know what the client thinks the state is? The browser is redirected from the login page to /callback (in the example), so the client doesn't have a chance to check the state. Should the client set a cookie so that the GET to /callback includes the state?
Create the session state on the server-side, store its value in session (encrypted cookie or server-side storage cache (eg. Redis). Then during the code authorization grant flow, check its value as a first action in your callback. Some libraries might handle the check for you, or else you will have to do the ceremony of pulling the state value explicitly out of session storage in your code, and comparing that explicitly against the value of state that was returned to your callback endpoint.
If you are using Auth0 Hosted Login Page, and making a call to authorize endpoint, then you can just do it all server-side - see here. If you need to render a form on UI with state value then your Controller can pass the value of your state to the view layer as a value that gets interpolated. The key takeaway is that it is recommended to generate the value server-side, store it in secured session storage, and do the comparison server-side (in the callback) for code authorization grant flow (regular web app).

Returning a refresh token with the resource owner flow

I have created an authentication server that implements OAuth 2 for authorization and it also provides local password authentication using the resource owner flow.
At the moment I always return a refresh token along with the access token which was an acceptable thing to do when I first implemented the feature. However now I need to implement a remember me feature in the client that uses the server. I could always just save the refresh token in the client when the user ticks the remember me checkbox but the token would still exist on the server and be usable even though the user didn't want it to.
What I want to do is simply pass a parameter along with the request that tells me whether I should create a refresh token or not.
So my question is. Is there some standard or recommended way of doing this using the fields provided in the spec or is it acceptable to simply add a parameter to the request to handle this use case?
AFAIK, there is no standardized way to choose whether to issue a refresh token or not.

Is it normal for my __RequestVerificationToken to be different with every request?

I've Google'd, but haven't been able to determine if ASP.NET MVC's v4 RequestVerificationToken should be different for every request?
I notice this in all environments, even when running on a single server. The user is logged in, but when refreshing the page (F5) a different token is generated every time.
Is this normal or not?
This is completely Normal. No difference when a user is logged in or not.
Note that: Synchronizer token pattern is a technique where a token, secret and unique for each request, is embedded by the web application in all HTML forms and verified on the server side. The token may be generated by any method that ensures unpredictability and uniqueness (e.g. using a hash chain of random seed). The attacker is thus unable to place a correct token in his requests to authenticate them

Resources