I am making use of the Auth0 service for my user authentication, but I have been having issues whereby the client id keeps returning an invalid user token.
The API accepts access tokens normally and verifies it on the back-end of the application built using NodeJS but at the front-end using ReactJS and Next.JS, I don't get access to a valid access token.
It returns something like this:
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtMnp0eGs5ODkudXMuYXV0aDAuY29tLyJ9..rMSEQS4g-2NcYvqU.zmMlNypJoKyO-wwLcxJgnsvcUHrcTH5c7jnNskyvxldZn56Tc_YX1T2vUQpWWNAWTyItAkUJxM58iy-kj29hY3Bz-Y1Q0Vccu8RdEip8Hc6p9f6-pR6bFKwVlLNkhj5oovFSDTv_-WPcYT40E5fTWRxaV4sNnE3ml16Bcu_CtFECmxAuJZWQ83dxWXlgudWXT7dhNMTGEyL2hIhWHlwO-dWkjIGI1wJmEa8v5pd0atawYsJlzukUcfc54alugCjIVEd1_QnGFWseKY05Ezl5VrBZJuEBnS8Qi6lMRreVPZkat64j_5jvEsvC5F5jMO9Qi2c.ezk5VSWPKZYdhBKkUhWP1Q
Also, I tried switching to ID token because that is valid but the JWT validator always returns 'Invalid_user'.
Attached below are some visual representations of the issue faced.
You can try using the ID token with:
const jwtA = require("express-jwt");
var jwtCheck = jwtA({
secret: process.env.AUTH0_SECRET,
audience: process.env.AUTH0_CLIENT_ID,
algorithms: ["RS256"]
});
or confirm in your frontend application that all settings are correct
This looks like an opaque access token (see https://community.auth0.com/t/why-is-my-access-token-not-a-jwt-opaque-token/31028).
Auth0 uses these kinds of access tokens if you don't set a "audience" URL parameter in your /authorize API call (https://auth0.com/docs/api/authentication#database-ad-ldap-passive-). You can find the audience string in the Auth0 admin interface in the section "Applications -> APIs".
If you are using the Auth0 Next.js SDK, you can e.g. set the default audience via the "AUTH0_AUDIENCE" environment variable (see https://auth0.github.io/nextjs-auth0/modules/config.html#configuration-properties).
Related
I have an asp.net core ReactJS + web api (one project).
Im trying to obtain an access/authorization token so my UI can access the web api (with the [Authorize] attribute enabled). -- Note that the UI can access my web API if [Authorize] is NOT enabled.
So here is the steps my UI is taking to try to obtain a valid access token:
Option A - Using acquireTokenSilent()
User invokes msal's loginPopup().
After user logs in the msal's accounts has a valid user account.
Using the valid user account, the UI then makes a request to obtain a token via acquireTokenSilent().
This returns a token immediately, BUT unfortunately the access token appears to be invalid.
I verify that the token is invalid by using a simple token validator online: online token validating tool
Option B - Requesting access token via https URL
An alternate approach i tried is setting window.location.assign(url) from the UI itself where the url is:
https://login.microsoftonline.com/<my tenant>/oauth2/v2.0/authorize?
client_id=<my client id>
&response_type=token
&redirect_uri=https%3A%2F%2Flocalhost%3A7070
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
&response_mode=fragment
&state=12345
&nonce=678910
&prompt=none
&login_hint=<my email>
The interesting thing with this approach:
If i navigate to the url from the browser, i get a proper access token!
But if i call this from the UI (using window.location.assign(url)), then the access token is NOT valid (it is about half the size of a valid token).
Option C - Requesting access token via browser (this is not a viable option)
When i navigate to the "https://login.microsoftonline.com...." URL from a browser, i can get an access token as a response. This appears to be a valid token. Although this works fine, i am just curious why it only works when requesting directly from a browser.
My ultimate question is: what am i doing wrong in obtaining an access token which i can use as a Bearer token?
A side question is related to Option B: why does the browser way get me a valid token while the programmatic way does not?
I am trying to implement API Gateway authentication using Cognito Access Token from an authenticated user, as shown in the video -> https://www.youtube.com/watch?v=bj3yVT6j3XU
To get the access token I am performing 2 methods:
1) Getting “Access Token” with Hosted UI + Code + Postman:
In the cognito user pool, I access the Hosted UI in the “App Client Configurations”:
After clicking the button above, and signing up with an existing user, I get the code in the url, as shown below:
With this code, I go to postman and can have access to the access token, as shown below:
Still using Postman, I call the API url with the header containing the “Authorization”, and I successfully get the response:
2) Getting “Access Token” with Auth method in React js:
I already tried to get the access token using the Auth.currentAuthenticatedUser() and Auth.currentSession(), and I realized they are the same. So here I am going to show the access token from the Auth.curentAuthenticatedUser().
When I try to use this access token in the react js code it doesn’t work, and I get the following error:
When I try to use this access token in the Postman, it also doesn’t work:
When I use the access token from the Hosted UI in the React js code, it works perfectly:
My questions are:
• Why I am getting different “Access Token”?
• How can I get the right access token in the React Js?
I found the solution - credits to Chirag from SrceCde.
The API call was "unauthorized" when I was using the AccessToken from the Amplify on React JS, due to scope.
The accessToken is generated with aws.cognito.signin.user.admin scope, as show the image below:
For that reason, it is necessary to enable the "aws.cognito.signin.admin" OAuth scope in the Cognito User Pool, and also consider the "aws.cognito.signin.admin" OAuth scope in the API Gateway for the API you want to call.
After doing that, you can get the accessToken with the Auth.currentAuthenticatedUser() method, as I was already doing.
At work we are making an SPFx Web Part React client app that deploys to SharePoint as a Web Part. Our back-end is a ASP.NET Core 2.2 Web API that is secured using Azure Portal's built in Authentication feature. The front-end is using AadHttpClient that magically handles the authentication by taking the context of the current page (SharePoint) that has the user already logged in. Doing so, silent authentication occurs and the API call is successfully made with authentication successfully passed. The AadHttpClient is supposed to magically bundle up the token in the request header that gets sent to the back-end Web API. I still need to debug the live development app and see how to retrieve the Bearer Token in the back-end Web API. These are my next probable steps?
Would I just probably use 'string bearerToken = Request.Headers.....;' or 'string bearerToken = Request.Headers["KeyValue"]' to get the token itself?
Assuming I can get this Bearer Token, how can I check the caller's user information? Is it just var userName = User.Identity.Name;? Or would I or could I use the token and some how make a call to Microsoft Graph API to view the user's info?
If you are using ASP.NET Core and using default authentication then things are bit easier. From documentation you can see that several tokens are injected in the request header based on Identity provider so in your case you have to look for following headers which Azure AD injects. These headers would contain ID Token which you would need to verify the claims and get user information.
X-MS-TOKEN-AAD-ID-TOKEN
X-MS-TOKEN-AAD-ACCESS-TOKEN
X-MS-TOKEN-AAD-EXPIRES-ON
X-MS-TOKEN-AAD-REFRESH-TOKEN
Ideally all the claims are injected automatically in ClaimsPrincipal
you can find more here
Official Docs
How To extract Token
I have implemented an ASP.NET Core MVC Client using Hybrid flow, and I am wondering what the HttpContext.Authentication.GetTokenAsync("access_token") does.
If you need more background on my question:
The instructions for accessing an API from with an ASP.Net Core Client App Controller Action are generally as follows:
var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
var client = new HttpClient();
client.SetBearerToken(accessToken);
var response = await client.GetAsync("http://localhost:5001/api/stuff");
There is magic in httpContext.Authentication.GetTokenAsync("access_token") :-)
I am wondering what this function might be doing. Is it decrypting the access token from a cookie in the MVC App Domain? ... from the ID4 Domain?
I am sorry but I have been unable to find sufficient documentation on what this does or finding the cookie the access token may be in. I have looked here:
https://learn.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.authentication.authenticationtokenextensions
Does anyone know what it does? A link to more thorough documentation is a totally appreciated answer.
TU!
You can store arbitrary tokens in your authentication cookie in and that method simply returns one with a given name. Actually setting that would have happened during the sign in process. So in short, it comes from the authentication cookie for your client application and would typically be set at the point of sign in using IdSrv4.
It's a way for the client webapp to confirm separately whether the user really did authenticate with IdentityServer (the user comes to your webapp, the webapp forwards the user to IdentityServer for authentication). The id_token comes back with the user to your webapp in a browser cookie, basically when your webapp sees that id token, it does an independent check with IdentityServer, and if it represents a valid user authentication, you'll get an access token back. You can use that access token to get user claims from the userinfo endpoint.
After all of the above, you can take one of the claims and use it as a key for your application's roles/permissions.
I have an MVC site with an embedded angular client and I've recently implemented an anti forgery XSRF token as a security measure.
I have set it up in Startup.cs as follows:
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
app.Use(next => context =>
{
if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase))
{
// We can send the request token as a JavaScript-readable cookie, and Angular will use it by default.
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
And I've implemented it within my angular front-end like so:
{ provide: XSRFStrategy, useFactory: xsrfFactory}
export function xsrfFactory(): CookieXSRFStrategy {
return new CookieXSRFStrategy('XSRF-TOKEN', 'X-XSRF-TOKEN');
}
And protecting my controllers like:
[Authorize] //Validation of AzureAD Bearer Token.
[ValidateAntiForgeryToken]
public class UserController : Controller
It is intended that the X-XSRF-TOKEN header be validated with any call to my API, and this works successfully for all calls in the original session. However, my app uses Adal to log the user in, and after the redirect from a successful login, this validation step fails and I receive a 400 from my API for any subsequent calls.
The original X-XSRF-TOKEN header is still sent with all outgoing requests from my angular client after the login so I suspect it must be that my server side no longer has the token to validate against, or my server has generated a new one and my client doesn't retrieve it. But for whatever reason it breaks down and it's very hard to debug without creating some custom filter so I can see what's going on inside it.
Is there a way to reset this token after a client side redirect so that both my server and client share common knowledge of it again? Or should I be generating the token in my Index.html for example?
EDIT
Edited controller decoration above for missing [Authorize] attribute.
So my controller is protected by a step validating the AzureAD Bearer token as well as the Anti-Forgery validation. Removing the AzureAD Validation as a test did not resolve the issue, oddly.
Error on failing API calls displays in output after Adal login as:
The provided anti-forgery token was meant for a different claims-based user than the current user.
Based on my understanding, you were protecting the controller using token. For this issue is expected, you can refer the progress of validate the anti-XSRF tokens from below(refer this link):
To validate the incoming anti-XSRF tokens, the developer includes a ValidateAntiForgeryToken attribute on her MVC action or controller, or she calls #AntiForgery.Validate() from her Razor page. The runtime will perform the following steps:
The incoming session token and field token are read and the anti-XSRF token extracted from each. The anti-XSRF tokens must be identical per step (2) in the generation routine.
If the current user is authenticated, her username is compared with the username stored in the field token. The usernames must match.
If an IAntiForgeryAdditionalDataProvider is configured, the runtime calls its ValidateAdditionalData method. The method must return the Boolean value true.
Since you were developing the SPA application with back-end web API, when the request to the web API, it will always issue the anti-XSRF token with no identity. And when you send the request to the back-end with anti-XSRF and Azure AD token, this time the web API already authenticate the request via the Azure AD token. And it will always return false when checking anti-XSRF token to match the identity information.
In this scenario, if the back-end only using the bear token authentication and store the token with session storage, there is no need to enable XSRF prevention since others is not able to steal the token and forge the request.
If your back-end also support the cookie authentication or basic auth, NTLM etc, you can disable the identity checking by adding the following to your Application_Start method: AntiForgeryConfig.SuppressIdentityHeuristicChecks = true.(refer this link)
More detail about XSRF/CSRF abouth oauth and web API, you can refer the threads below:
How does ValidateAntiForgeryToken fit with Web APIs that can be accessed via web or native app?
AntiForgeryToken does not work well with OAuth via WebAPI
Try replacing [ValidateAntiForgeryToken] with [AutoValidateAntiforgeryToken]
https://github.com/aspnet/Antiforgery/blob/dev/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenGenerator.cs