Hi I am trying a simple authentication of a webapi using AzureAD. In that when we add the connected services using the Azure AD, the Startup.cs class adds the below code
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
});
When i went through some of the authentication tutorial, i am seeing people are asking to use some thing like the one shown below
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions{....
}
What's the difference between these 2, aren't we supposed to be using AzureAD options going by the name and since we are using the AzureAD Connected Services for Authentication of the webApi. Can some one clarify the same?
Cookie Authentication
Cookie authentication uses HTTP cookies to authenticate client requests and maintain session information. It works as follows:
The client sends a login request to the server.
On the successful login, the server response includes the Set-Cookie
header that contains the cookie name, value, expiry time and some
other info
The client needs to send this cookie in the Cookie header in all
subsequent requests to the server.
On the logout operation, the server sends back the Set-Cookie header
that causes the cookie to expire
Note: Cookie authentication is vulnerable to Cross-Site Request Forgeries (CSRF) attacks, so it should be used together with other
security measures, such as CSRF tokens. For more details you could take a look here
Azure Active directory Authentication:
As you know Azure Active Directory is a modern Token based authentication which provides Single Sign-On (SSO) that allows a user to use one password (or smart card) to authenticate to multiple servers on a network without reentering credentials. This is an obvious convenience for users, who don’t have to remember multiple passwords or keep going through the authentication process over and over to access different resources.
Main thing is AAD uses JSON Web Token(JWT). On receiving the credentials from client the server validates the credentials and generates a signed JWT which contains the user information.
Its also support most popular modern authentication protocol as following.
OAuth 2.0
OpenID Connect
WS-Federation
SAML 2.0
Note: the token will never get stored in server(stateless).
So the main difference is cookie based authentication usually stores your user sensitive information on server because it maintains session which seems vulnerable on the other hand token based authentication is secure and don't preserve sensitive information.
see the basic difference of these tow architecture below:
Select Right Authentication:
Here I am showing you a flow chart which enhance your idea to choose right authentication for your application. Take a look below:
You could also have a look here for better clarity. Thank you very much. happy coding!
Related
Background
I'm trying implement a browser-based login for a native mobile app from an existing Single Page Application. It uses WebView to render the SPA and it uses Keycloak OIDC as its Identity Provider.
The SPA and IdP is located in completely different domain and authentication is done by redirecting to the SPA domain after a successful login and retrieving the active session (cookie) from IdP domain in one of the SPA's server. The authentication check is achieved by using keycloak middleware which I believe is the protect.js
Summary:
Perform Login -> auth.idp.com
Redirect -> best.app.com
Is Login? -> best.app.com/login
Does auth.idp.com session exists?
User is logged in, redirect -> best.app.com
Token is passed in the URL and is stored only in memory
Token is used to establish WebSocket connection
Issue
Based from the spec, the authorization should happen in the browser / in-app browser, and authorization code must be passed via custom URL scheme. Having that in mind, the SPA that resides in the WebView of native mobile app will never establish a session from IdP's domain since this will be delegated from the browser which is on a different process and obviously using a different cookie store than on WebView in the mobile app, which makes our existing solution to break because it is relying on the IdP's domain cookie.
Proposed Solution
The issue I described above can be mitigated by cutting the reliance on IdP's session and by managing the SPA's own session, which basically means storing the token persistently that can be obtained from the IdP (which the current solution doesn't do).
(I don't want to detail much of the solution since I just want to focus first on the concept of storing the token. I think it's better for me to put this in a separate discussion if someone is interested)
Opinion
It seems like the current implementation doesn't really follow the best practice for OIDC flow but somehow, Keycloak has made some middleware to remove the need to use these tokens (authorization code, id token, and access token)
Relying on IdP's session when implementing SPA or non-web apps seems like not an option, because there is no way to obtain the cookie without reloading the page and provided that IdP session exists in the same cookie store as the SPA.
Redirecting to the IdP's session is not a good user experience for SPA. See the same sentiment here but it seems it does not have any answer: https://lists.jboss.org/pipermail/keycloak-user/2016-October/007937.html
Question
With regards to my proposed solution, i.e., storing the token retrieved from IdP, is there any security flaw or something non-industry standard it's going to introduce? If so, what are those?
Is it typical for OIDC flow to rely on IdP's session (cookie) to check if user is logged in or not?
If answer from #2 is NO, is that authentication flow specific for Keycloak only or does it exists for other IdP as well?
If answer from #2 is YES, is it common for IAM solution to programmatically check if the IdP domain contains a valid session (cookie)?
Is the current implementation flawed knowing we are aiming for SPA?
How does Keycloak handle sessions?
If you're using the default Keycloak middleware in your server and use keycloak.protect() for protecting endpoints, it checks on the request.session['keycloak-token'] which contains the access_token that was created during the token request after user login. If this exist and valid, it means user will not be redirected to Keycloak login page.
How does Keycloak create sessions?
Providing username and password which can be done manually using Keycloak's login page.
Cookies - if you pass valid cookies that are recognized by Keycloak, i.e., KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY, ..., a session will automatically be created.
How to access protected resources?
When using the keycloak-connect client adapters, you can access protected resources if the user agent (browser/app), has a valid session in your server OR if the request contains valid Authorization header.
Standard Solution
Access protected resource via Authorization header and use access_token which the keycloak.protect() also accepts. You can obtain this token in a standard way using Chrome Custom Tabs for Android and ASWebAuthenticationSession for iOS. You can also use AppAuth (iOS, Android) to lessen your work.
Store the refresh_token and access_token from native mobile and inject this in the HTTP request of WebView if possible.
Have a way to check for access_token validity and use refresh_token to request for a new one. If requesting for a new one fails, i.e., the authorization server verifies it's not valid anymore, that means users would need to re login again.
By using the standard solution I have proposed above, you should not need to create a band-aid solution for your issue. Hope this helps anyone that have faced similar issue.
Context:
1 spa
1 api
1 existing passport strategy with jwt
Feature:
Connect additional account with oauth to the existing account
I already have an authentification using passport on nodejs.
This generates a jwt allowing the users to authenticate them with a bearer token in the header of each request to the api.
I would like to add an additional oauth connection to the existing account (actually it is docusign but I think the problem could be the same with other connections).
When there is the redirection with the authorization code, I cannot identify the user which has initiated the connection because I don't have the bearer token in the request header anymore and the data between the two accounts can be different (different emails for example).
Is there a workaround for this or did I miss something?
Thank you for your help
Passport has an Authorize method which can be used to authenticate with a secondary IdP. For example:
Use Passport#Login to enable the user to login to your application's primary IdP
Use Passport#Authorize to enable the user to authenticate with a secondary IdP (such as DocuSign) as needed.
Regarding state for your redirect method (determining which IdP should be used to exchange the authorization code for an access token):
You can use the state parameter that is sent as part of the OAuth authorization code grant flow. But be sure to also use the parameter as a random nonce to guard against a CSRF attack. Eg, send idp1|random_nonce so you can both check the nonce and know that you should communicate with idp1, not idp2.
You can use your application's session machinery to maintain your app's state knowledge of which IdP you're working with at the time.
The only one I can think of is having 2 apps. Each can run on a different port or vd. Each would have their own passport strategy. The two apps can redirect to eachother and/or communicate using API endpoints to pass data between them.
Please bear with me while I explain my problem and the solutions/guides I have found.
Description: In my company, we have one product that have multiple modules. Each module is its separate backend and frontend. We have JavaEE/JakartaEE with JAX-RS as our backend stack and React as for our frontend. Until now we are using Basic Authentication using the JavaEE Security via Sessions, but because the product is evolving and we need mobile clients and allow third parties to access the data, we have decided to integrate OAuth2/OpenID Connect into our application.
Since there are multiple implementations out there that provide OAuth2 functionality, we are currently looking into a few available options. (Keycloak and ORY Hydra for example). The decision which we will choose depends on how much work we want to do change the existing structure of the application how we handle the users in the database. But regardless of which implementation we opt for, we have similar questions going forward.
Questions
How do the react applications handle login process and token storage?
Every documentation says: If the user is not logged in s/he is redirected to the login page. Where after login and consent he is redirected back to the app (After completing the oauth2 workflow obviously) with the Access/ID Token for the resource server and/or Refresh Token for refreshing the Access/ID Token.
Now here is what is not clear to me:
Since this is our own React app, we do not want to show the consent screen, like in apps from Microsoft/Google etc you do not see any. I guess this is possible by setting a value in the request itself, or skipping the consent screen based on the client id but I just want to make sure.
Next is where do I store the Access and Refresh Token? Access Token should be sent as the Bearer token with each request. So it can be stored in local storage because they are short lived, but the refresh token should be stored securely. Like in a secure http cookie?. If that is the case, then the server has to set it. If this is correct is this how the flow will look like?
Our React App (Not logged In) --> Login Page (Another React Page) --> User Enters Credentials --> Java Backend --> Authenticates the user --> Initiate the OAuth2 process --> Get the Access and Refresh Tokens --> Set them as secure Cookies --> Return the authenticated response to frontend with the cookies --> Login Page redirects to the previous page --> User continues with the app
This does not feel correct. How would PKCE help in this case?
Assuming what I wrote above is correct, I would need different login flows when the users logs in from our own app or from a third party app. That can however be determined by checking client ids or disabling password flow for third party clients.
The same would be applicable then for the refresh token flow too. Because for my own app I have to set the cookies, for third parties this has to be directly from the OAuth Server
Resources I have read/researched:
https://gist.github.com/mziwisky/10079157
How does OAuth work?
Edit: Adding more links I have read
What is the purpose of implicit grant
Best practices for session management
RESTful Authentication
And of course various writings and examples from Keycloak and ORY Hydra also.
I am currently trying both Keycloak and ORY Hydra figuring out which fits our needs better.
Thank you all in advance!
You don't have to show the consent screen. Here's an example of a React app authenticating using the Authorization Code Grant: https://fusionauth.io/blog/2020/03/10/securely-implement-oauth-in-react (full disclosure, this is on my employer's site but will work with any OAuth2 compliant identity server).
The short answer is that it's best for you to avoid the implicit grant, and have the access and refresh tokens stored in some middleware, not the browser. The example in the link uses a 100 line express server and stores those tokens in the session.
I wrote a bit about PKCE. Excerpt:
The Proof Key for Code Exchange (PKCE) RFC was published in 2015 and extends the Authorization Code grant to protect from an attack if part of the authorization flow happens over a non TLS connection. For example, between components of a native application. This attack could also happen if TLS has a vulnerability or if router firmware has been compromised and is spoofing DNS or downgrading from TLS to HTTP. PKCE requires an additional one-time code to be sent to the OAuth server. This is used to validate the request has not been intercepted or modified.
Here's a breakdown of the various OAuth options you have (again, this is on my employer's site but will work with any OAuth2 compliant identity server): https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows You can allow different flows for different clients. For example, you could use the Authorization Code Grant for third parties and the Resource Owner Password Credentials grant (which essentially is username and password) for your own applications.
I'm not sure I answered all of your questions, but I hope that some of this is helpful.
The OAuth 2.0 Security Best Current Practice should be consulted. Even though it is still a "Internet Draft" it is mature and has been implemented by several vender implementations.
In general the OAuth 2.0 Authorization Code with PKCE Flow is the recommendation regardless of the use of Bearer tokens or JWT.
You should also consider reading about WebAuthn (Where there is not password)
I am using Open ID Connect and requesting tokens from Azure Active Directory. I am using the authorization code flow, so I am receiving both the id_token and the access_token. I am using .NET Core.
My configuration of Open Id Connect is as follows:
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
Notice the Save Tokens set to true
When the user is logged in, I am able to retrieve both the tokens as follows:
string accessToken = await HttpContext.GetTokenAsync("access_token");
string idToken = await HttpContext.GetTokenAsync("id_token");
My question is, where these tokens are actually being saved, and how can I configure how these tokens are being saved?
I also heard that in the authorization code flow, the identity provider will return the authorization code, and the server would then use that code to request the tokens. However, I am not doing any of that programmatically and I am still able to retrieve the tokens. Is this something handled automatically with Open Id Connect?
Where these tokens are actually being saved?
As the OpenID Connect protocol diagram architecture describe, When a new session is started, a new cookie is returned to control this session. This "sesion cookie" is created based on "ID Token" and as long as this cookie is valid, user will be considered as authenticated. As you are using, OpenID Connect (OIDC), it create the cookie and save token there. you could refer this docs
How can I configure how these tokens?
If you want to configure your token mechanism Microsoft provides library fro that. You can use ADAL or MSAL for your own configuration.
Is this something handled automatically with Open Id Connect?
Thought its has some background mechanism but you have to use authentication library to handle on your application code. You could refer official docs
For more details you could refer flowing docs
Authentication implementation
Authentication Libraries
Code sample
response_type is set to code indicating that you are using the Authorization Code Flow.
When you use OIDC auth code flow along with clientid and clientsecret to get token, the work process is as below:
1.The user clicks Login within the regular web application.
2.Auth0's SDK redirects the user to the Auth0 Authorization Server (/authorize endpoint).
3.Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
4.The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the regular web application.
5.Your Auth0 Authorization Server redirects the user back to the application with an authorization code.
6.Auth0's SDK sends this code to the Auth0 Authorization Server (/oauth/token endpoint) along with the application's Client ID and Client Secret.
7.Your Auth0 Authorization Server verifies the code, Client ID, and Client Secret.
8.Your Auth0 Authorization Server responds with an ID Token and Access Token (and optionally, a Refresh Token).
I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.