How authorization code flow works in single page applications? - reactjs

Hi I am exploring some of the authentication and authorization flows with respect to azure active directory. I was using previously oath implicit flow in single page application. After spending time in reading microsoft documentation, I have understood following with respect to implicit flow.
Implicit Flow:
Single page javacript application uses implicit flow to get obtain access token from azure active directory. It directly calls token endpoint to obtain the token so this makes implicit flow less secure.
Authorization Folw in .Net Web application
Whenever we use .Net core web mvc application with authorization code flow, first call will happen in browser to authorization endpoint to get code. In browser we could see the request made to authorization end point. In request url I will pass response type as code then client id and redirect ui. Here first handshake take place between browser and authorization end point. This handshake returns code to the redirect uri. Next part, application has to make POST request to token endpoint to get access token. Code received in first step I will send in token request. In this request I will include client secrete also, redierct uri also. But whenever I make first GET request to authorization endpoint I will not pass client secrete. This is because Its not good to expose secrete in browser. So in second post request I will include client secrete also. Once I get access token I will add it in api request header to make secured call to apis.
This is the authorization code flow flavor I have understood with respect to .Net core web application. now I have another flavor of authorization code with respect to single page application.
Authorization Code Flow in React Web App
I have SPA react application which uses MSAL library. I have cloned sample application from github https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/tree/main/3-Authorization-II/1-call-api/SPA.
Whenever I run this application, and sign in first call will happen as below
https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=https://login.microsoftonline.com/c5ffa990-7e0a-4bf6-6c04-79ab98e05931/oauth2/v2.0/authorize
I am trying to understand this request. I have query string appended to the url authorization_endpoint=https://login.microsoftonline.com/c5ffa990-7e0a-4bf6-6c04-79ab98e05931/oauth2/v2.0/authorize so this may be used to return the code from authorization server.
Immediately next call will happen https://login.microsoftonline.com/c5ffa990-7e0a-4bf6-6c04-79ab98e05931/oauth2/v2.0/token
to get access token and in request in FormData section I could see following parameters
client_d, redirect_uri,scope,code
In code I see some code value hopefully received from authorization endpoint. anyway this api returned me access_token.
Now coming to conclusion, In .Net core web application and React SPA application both places I am using authorization code flow.
In .Net core authorization code flow I am making use of client secrete whenever trying to obtain access token. All this happen in server side in secure manner. In react also I am using Authorization code flow but I am not using Client secrete anywhere.
In react app also I am making two requests one for authorization endpoint to get code and another to get token. All this I can see in browser itself but then How can I consider this is as secure?
In .Net web app and react app both apps making use of authorization code flow but it behaves independently depends on the type of application.
After going through several documents and videos over the internet I concluded myself as
When Authorization code flow used with server side web apps like .Net core MVC, It makes use of client_secrete to get access token and this call will happen in server side so client secrete not exposed through browser to the users
When Authorization flow used SPA applications without server side support, first it will make call to get authorization code then It will make post request to get access token WITHOUT client_secrete.The only way the authorization code grant with no client secret can be secure is by using the “state” parameter and restricting the redirect URL to trusted clients.
So I am concluding myself as when we use server side web app with authorization code flow we can make use of client secrete but in case of SPA we are not making use of client_secrete.
I have understood above concepts and explained what I understood and also I listed the confusions I got after implementing 2 flavors of authorization code flow in web app and spa app. can someone help me If my understanding is correct or not, If my understanding is wrong, where exactly I understood wrong? Can anyone help me with respect to this. Any help would be greatly appreciated. Thanks

Authcode flow is an OAuth 2.0 workflow, you can use it in any kind of client (Web/mobile/SPA).
Clients should be using MSAL library to communicate with AAD/B2C with PKCE which is used to secure authorization code grants via Proof Key for Code Exchange (code_challenge) with S256 encryption.
Authcode Grant Flow spec:
If you are using B2C, your entry endpoint is:
https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=code
&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
&response_mode=query
&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6%20offline_access
&state=arbitrary_data_you_can_receive_in_the_response
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
&code_challenge_method=S256
that will display the SignIn-SignUp-Social Login Form. Just navigate to this URL with you App ClientId registered inside B2C.
You also can take a look to the custom policies starter pack to adapt your workflow to your needs (claims).
If you change response_type=code for response_type=id_token you will get a Token that can be used to authenticate against your restricted resources (API's) after all login process.
Or you can use a second call to the token endpoint to get it.
Token endpoint:
POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
code=XXXXXXXXXXXXX parameter is the access_code returned from first GET request.

Solutions to this is to switch to implicit flow, where there is no need of exchanging code for access token. But keeping access token in web application still vulnerable as this can be exposed using XSS or similar kind of attacks.
Other best practice is https://curity.io/resources/learn/the-token-handler-pattern/

Related

Spring Boot, React and OpenId Connect

We have a use case where we are implementing OpenId Connect in a Spring Boot (backend) + React (frontend) application. We are implementing Authorization code flow.
The backend and frontend are on separate domain.
Here is the flow that happens:
The backend returns the generated URL which can be open by the React App for login (redirecting to Cognito in our case - but it can be anything) - or even this URL can be generated on the Frontend itself - since the clientId will be exposed in the URL anyway
The user logs in, a request is sent to the redirect uri, where the Authorization Code is used to get an access token, id token and refresh token
When this ends, we have the tokens but how do we transfer them to the React App in the other domain? I assume redirection and passing the tokens as query parameters makes sense - something like return "redirect://http://www.yourfrontenddomain.com?access_token" + tokenValue;
Am i missing something here or my approach is fine?
Using Implicit flow here would be easier - but this is less secure and only recommended for Javascript apps - here we have a mix of Backend + Frontend.
Thanks a lot in advance
Ok it seems i was not understanding the concepts correctly.
Authorization code flow with PCKE is exactly made for this use case - to be used in SPA's or Mobile clients.
By using that flow, we can just use Spring Security and just validate the tokens on the backend (without generating them or anything)

Authorization and authentication in web application with ASP.NET Core backend and React frontend?

I have a web application, where the frontend is built with react.js and typescript and the backend is build with ASP.NET Core 3.1 and connected to a SQL Server. The SQL Server is used for saving data, which I can enter in the frontend.
Now I want to implement a custom authentication system, where I can protect different endpoints with an authorization. I know there are several ways to go for, but I don't want to use a service / library, where a user could login with his google account for example.
Jwt seems in my Opinion a good way to go here, but I really don't understand the whole system.
This article helped me already a lot: Implementing authentication and authorization with React hooks, .NET Core Web API, and SQL Server .After reading this, I don't understand the relationship between logging in and how my backend knows, that a user is logged in (for protecting my endpoints).
Of course I already read many articles about authentication and authorization for ASP.NET Core. I've read about different services like:
Auth0 (seems not a good idea, because you can login with google etc.)
IdentityUI (seems good, I've seen a few youtube tutorials but they are all using another project structure, where the frontend and backend isn't separated. So they are using the razor pages like Login.cshtml, but I don't want to render any pages in the backend, only in the frontend)
For authorization for my controller in the backend, I planned to use the following:
[Authorize] // to protect endpoint
[HttpGet]
public async Task<IEnumerable<>> GetData()
{
// some code
}
But as I already said: I don't know / understand how my backend knows if a user is logged in (and how to check it).
Could somebody provide me an appropriate tutorial or an article, where is explained, how to manage authorization and authentication for frontend and backend? Or maybe somebody knows, how to use the IdentityUI with a frontend build with react + typescript and a backend, which shouldn't render any pages.
Thanks for your attention :)
Well... for detailed flow how they work, here is RFC 6749, this is a pretty comprehensive collection of knowledge related to the topic and the easiest approach would be wiki page in general.
But to simplify the process, just get to know these things:
What is JWT
Jwt just a string that was generated by some algorithm from a public/private key pair(don't even care how it works, just give it a key pair, some lib on every language would do the rest). This JWT often contain all the information that needed to specify who the user is(big word right ? but actually, userId is enough for simple case).
It contain 3 different parts Header, Payload and Signature, and the string assured it cannot be interrupted(or just modify it as we wish, and the validation process would failed).
Further detail here.
What happen on server side?
The most basically flow was send user, password to server for validate who we are and our account exists. Then, server side would take some necessary info out of it to generate the JWT token. The server which generate JWT token was normally refer to Identity Provider.
Then that token was send back to client, and client save it somewhere for later use.
Client side use token to request other resource
Normally, Identity Provider would provide a .wellknow endpoint that contain all necessary info for other resources to gather for validation process.
Now, client side send a http request to these resources with the JWT token. They use info gathered from .wellknow endpoint to validate was the JWT valid. If it is, we are who we claim we are, authentication process success.
The end.
Over-simplyfied flow imagination in your specific case
React Client => Request login => Identity Provider => Jwt Token send back => React client save it somewhere.
React Client => Request some resource over http with the JWT token => Resource server validate it (through info from .wellknow endpoint) => Authentication success or fail => normal process => send response back to client.

Is it ok to pass OAuth access tokens to the Client

i'm still pretty new to web-development I worked myself through Web Development with Node and Express by Ethan Brown and currently i'm trying to get a good understanding for the examples given by Full-Stack React Projects by Shama Hoque.
Currently i'm trying to refactor a lot of things that used to be server-side-rendered to be handled in the React SPA client. One of these things includes a simple GitHub widget, my previous flow worked like this:
The client user authenticates with my server using a GitHub OAuth app.
The server stores the access Token returned to the callback in a database on the server.
The server makes calls to the GitHub API using the user access Token stored in the database.
The server processes the results, renders it in HTML and sends it to the client.
However I realized that there is also possibility to implement it like this.
The client user authenticates with my server using a GitHub OAuth app.
The server passes the access Token returned to the callback back to the client
The client makes calls to the GitHub API using the user access token obtained from the server.
The client processes the results and renders it apropiately.
As far as I understand there is no inherent security risk doing this(a malacious user could interecept the access token when the oAuth provider redirects to the callback either way) and both flows have their up and downsides (e.g. 2nd flow produces less load on the server but also sacrifices control). Since I'm new to this and I came up with the 2nd flow myself I wanna double check if this is something thats ok to be doing or I've missed something, if so, what did I miss? Is there any other major down or upsides i'm not considering?
What you've implemented is the OAuth Authorization Flow. In this flow, the client (aka the browser) never gets the access token. Only your webserver gets it. And thus the client cannot make calls to the resource server (github). Your webserver makes the calls on the client's behalf.
You say:
a malacious user could interecept the access token when the oAuth provider redirects to the callback either way
However, if you implement the flow correctly, this is not true. This is because once you authenticate with the resource server, it only gives the browser an authentication code. This code is just a temporary ticket that can be exchanged for an access token. However, to exchange a code for the access token, you have to know a client secret. Only your web server knows the secret. So your browser sends the code to your server, and your server calls the resource server (github) with the code + secret to get the token.
The second flow you describe is the OAuth Implicit Flow.
This flow is very much what you described: After the user authenticates with the resource server, the browser ends up with the access token and just calls the resource server directly.
Both flows are very common. The Implicit flow is slightly less secure because there is more opportunity for Bad Guys to get access to the token in the browser's memory (or local storage, or cookie storage). The Authorization Flow is a bit more secure because the token stays on your server, and you do not have to depend upon users to keep it secure.

OpenId Connect Authorization Code flow in Angular JS

I am looking for best approach to implement the Open Id Authorization Code flow in Angular JS. Have got examples on Implicit flow to get the temporary tokens: id_token and access_token, but i need to get the long-lived token : refresh token.
Looks like I need to go for authorization code flow, where i would get the "code" based on the user credentials, and thereby using that "code" would get the refresh_token.
Ours is Angular/ Web API project(not using MVC).
Is it recommended to use authorization code flow at client side?
if so, what is the best approach/ best library that we can achieve this use case?
keep in mind that the implicit flow is the recommended one for SPA application like angular, because it's better to send and access_token with a short lifetime rather than sending a a long lifetime token that can be used easily to generate access_tokens. but if you insist you can use the Hybrid flow, authorization code flow is more for server to server communication :

How to use SAML authentication in a mobile application?

I'm trying to understand how an saml authentication flow could work in a mobile environment where the client (AngularJS based), api server (Node & passport based), and idp exist on different domains.
From what I've gathered the general practice is to have the server return a 401 to the client if there's no authentication present (i.e. the client didn't include a bearer token in the request). The client understands that a 401 response indicates to open up the login endpoint on the server. When the login endpoint is opened it makes a passport call to the auth provider (which redirects the user to the auth provider's site) and supplies a callback URL. When the user authenticates, the auth provider redirects to the provided callback URL, which allows the server to retrieve information from the auth provider's response and construct a token of some sort (e.g. JWT) that can be used by the client (i.e. included in the headers) when making REST calls to identify itself.
My question is: How does the client get the token from the server? Because we're in a redirect-based authentication flow, I can't just return token from the callback function; that would just display the token in the browser without handing it off of to the client. Does the server just issue a 302 redirect pointing back to the client domain and include the authentication token in a header? Maybe I should not redirect from the client to the server in the first place and instead window.open() and use window.opener.postMessage or is that too old fashioned/mobile-unfriendly?
This question talks about authentication against a SAML IDP, but I'm interested in getting more details specifically about that last bullet point and how it would work with an AngularJS-based client.
Many examples I've seen online are either a single domain using OAuth/SAML (passport-saml-example), which avoids the issue of having the client exist on a separate domain, or use two domains with basic authentication, which avoids the issue of redirecting to some third party for authentication, but I'm having trouble finding good examples that uses all the bits and pieces I'm trying to work with.
This blog post seems very close to what I'm trying to accomplish (see googleSignInCallback) and uses a 302 redirect like I imagined but that solution relies on explicitly knowing the client URL to redirect to, which seems like it could be problematic if I wanted to support multiple client types (i.e. Native applications) in the future.
Eventually I was able to work together a solution by having my application open a browser window (Cordova's InAppBrowser) to a SAML-enabled application, have that application complete the normal SAML flow, and then that SAML-enabled application generated a JWT. My mobile application was then able to extract the JWT string from the browser window with the InAppBrowser's executeScript functionality. Then I could pass that JWT string along to my API server, which was able to validate the JWT is properly signed and trusted.
After I implemented my solution I saw that there was similar functionality available on github:
https://github.com/feedhenry-templates/saml-service
https://github.com/feedhenry-templates/saml-cloud-app
https://github.com/feedhenry-templates/saml-cordova-app
Hopefully this helps anyone else trying to deal with this issue!

Resources