I am building a authentification with AWS Cognito built-in web page.
(I am using Cognito User Pool and Identity Pool without any other provider)
The Cognito webpage return me a token (idtoken) and I put it cookie.
When I try to use this token to get credential, with the following code :
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'eu-west-1:XXXXXXXXXXXXXXXXXXXXXX',
Logins: {
'cognito-idp.eu-west-1.amazonaws.com/eu-west-XXXXXX':
CookieHelper.getCookie("session-id")
}
});
AWS.config.credentials.getId(...);
I get this error :
Error: Invalid login token. Missing a required claim: aud
How can I solve this problem?
Did I miss some steps between to get credentials?
May be I miss somthing in Cognito configuration?
I was using the wrong token.
The build-in webpage return 2 token : One for session-token and one for id-token.
With the other token, I can get credential.
Hope that will help some one.
Related
I have an SPA that uses B2C as its certification.
not AD, im using B2C.
Now I want to display user information on the SPA,
so I want to use MsGraphAPI to get data from B2C.
Therefore, we are trying to obtain an access token using credential flow.
The code is as follows
requestUri = "https://login.microsoftonline.com/{tenandId}/oauth2/v2.0/token";
var params = new URLSearchParams();
params.append("grant_type","client_credentials");
params.append("client_id","XXXX");
params.append("client_secret","ZZZZ");
params.append("scope","https://graph.microsoft.com/.default");
const response = fetch(requestUri, {
method:"POST",
body:params
});
At this time, the developer tool shows a corrs error.
The following error.
access to fetch "https://login.microsoftonline.com/{tenandId}/oauth2/v2.0/token" from origin "http://localhost:3000" has been blocked by CORS policy.
How can I resolve this?
SPA is available at http://localhost:3000.
Is the localhost no good?
The purpose of authenticating is to get user information. You can insert any attribute into the token, and then parse the id_token to display the users profile information in your application. Calling MS Graph API for this seems counter intuitive.
Next, you shouldnt be using client_credentials in your SPA, those are secret credentails, and should only be used by your server. By exposing those credentials in your SPA, any user could extract them and use them to read your entire directroy store. This is why you are getting a CORS error, it's never supposed to be running on the client browser.
I am using Blazor WebWebAssembly as my frontend and AWS Cognito as my IDP.
I can successfully login to AWS Cognito, but not able to get the access token with the following code because of the “X-Frame-Options“ directive set to “DENY“ error.
private async Task WriteTokenToConsole()
{
var tokenResult = await TokenProvider.RequestAccessToken();
if (tokenResult.TryGetToken(out var token))
{
System.Diagnostics.Debug.WriteLine(token.Value);
}
}
Yet, if I switch the IDP to Identity Server 4, I can get the access token no problem.
According to this comment https://github.com/dotnet/aspnetcore/issues/22651#issuecomment-640565340 , it is because Cognito is not being standard compliant?
Is there a way to work around this?
Thank you
I was able to access it via the code on: How do I get the id_token in Blazor WebAssembly after authenticating with OpenId (Cognito)?
I've since abstracted that into an extension to JSRuntime to make it easier to re-use across my code. But it seems to work fine for me.
I'm building an API which is called by a SPA (angular).
The user is authenticated using Azure AD and the API uses AzureAdBearer for its authentication.
public void ConfigureServices(IServiceCollection services)
{
[...]
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureActiveDirectory", options));
[...]
}
I need to call Graph API and would like to do it on behalf of the connected user.
I have seen this question: Accessing MS Graph from API on behalf of user currently signed in to separate web client which really looks like the solution I try to implement.
I try to replicate this proposed solution here: https://joonasw.net/view/azure-ad-on-behalf-of-aspnet-core
As I understand it I need to configure the JwtBearer settings, but how can I call the .AddJwtBearer if I already have .AddAzureADBearer.
AddAzureADBearer itself calls the AddJwtBearer (cf. here)
I created a secret in the app registration of my API and used it to implement a IAuthenticationProvider to get the token on behalf of the user, but I get an error AADSTS65001.
I guess this is because I'm missing the AddJwtBearer configuration to save the user's token in cache, but I'm not really sure.
I don't really understand the solution proposed on the question here.
UPDATE
Thanks to Tony Ju's answer I have been able to authenticate. But when I call graph api I get Authorization_RequestDenied Insufficient privileges to complete the operation.
I don't know why but can't manage to configure Fiddler properly to capture the request to Azure AD. I enabled ADAL logs and got this
[Information][False]: 2020-01-09T09:11:12.1104926Z: AdalLoggerBase.cs: ADAL PCL.CoreCLR with assembly version '5.2.4.0', file version '5.2.4.0' and informational version '5.2.4' is running...
[Information][True]: 2020-01-09T09:11:12.1183853Z: AdalLoggerBase.cs: === Token Acquisition started:
Authority: https://login.microsoftonline.com/d6397071-8e3e-45d2-a2d6-36698acf0fea/
Resource: https://graph.microsoft.com
ClientId: [...]
CacheType: Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache (0 items)
Authentication Target: User
[Verbose][False]: 2020-01-09T09:11:12.1395851Z: AdalLoggerBase.cs: Username provided in user assertion - False
[Verbose][False]: 2020-01-09T09:11:12.5277838Z: AdalLoggerBase.cs: Loading from cache.
[Verbose][False]: 2020-01-09T09:11:12.5395969Z: AdalLoggerBase.cs: Looking up cache for a token...
[Information][False]: 2020-01-09T09:11:12.5467711Z: AdalLoggerBase.cs: No matching token was found in the cache
[Information][False]: 2020-01-09T09:11:12.5706903Z: AdalLoggerBase.cs: No matching token was found in the cache
[Verbose][False]: 2020-01-09T09:11:12.5736362Z: AdalLoggerBase.cs: Looking up cache for a token...
[Information][False]: 2020-01-09T09:11:12.5764248Z: AdalLoggerBase.cs: No matching token was found in the cache
[Verbose][False]: 2020-01-09T09:11:12.5804061Z: AdalLoggerBase.cs: Either a token was not found or an exception was thrown.
[Verbose][False]: 2020-01-09T09:11:12.5844932Z: AdalLoggerBase.cs: Cannot invoke the broker directly, may require install ...
[Verbose][False]: 2020-01-09T09:11:12.5891021Z: AdalLoggerBase.cs: Check and AcquireToken using broker
[Verbose][False]: 2020-01-09T09:11:12.5919785Z: AdalLoggerBase.cs: Broker invocation is NOT required
[Verbose][False]: 2020-01-09T09:11:12.9510499Z: AdalLoggerBase.cs: Storing token in the cache...
[Verbose][False]: 2020-01-09T09:11:12.9583491Z: AdalLoggerBase.cs: An item was stored in the cache
[Information][True]: 2020-01-09T09:11:12.9917987Z: AdalLoggerBase.cs: === Token Acquisition finished successfully. An access token was returned: Expiration Time: 09/01/2020 10:10:54 +00:00Access Token Hash: GtaeLmKsVSj82umwxVcgghW3/X/N2hKhaxyb7XBbBU0=
User id: 3b224748-42c5-406d-a0c0-e9c9f5238361
I used this code to get the token:
var userAssertion = new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer", user.upn);
var authContext = new AuthenticationContext(_aadOptions.Authority);
var clientCredential = new ClientCredential(_aadOptions.ClientId, _aadOptions.ClientSecret);
var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion);
I tried to rewrite it for MSAL instead of ADAL but didn't success.
Should the scope needed for the graph api request should be in the initial user login or do we expand the scope in the on-behalf-of user request token ?
Please check the permissions of your web api permissions. Go to App registrations->find your web api app->permissions.
If you have permissions which need admin consent, you need to grant admin consent for your tenant.
If you don't have any permissions which need admin consent, try to grant user consent by sending a request like the following example
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=cbc32712-****-4532-802d-303998a6e712
&response_type=code
&redirect_uri=http://localhost
&response_mode=query
&scope=https://graph.microsoft.com
&state=12345
I guess this is because I'm missing the AddJwtBearer configuration to save the user's token in cache, but I'm not really sure.
You can simply set breakpoint in IAuthenticationProvider to confirm whether it gives token via string token = await httpContext.GetTokenAsync("access_token"); . I think it should be there , if there is no access token , you can try below ways :
Override the JwtBearerOptions :
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
{
options.SaveToken = true;
options.Events = new JwtBearerEvents
{
OnMessageReceived = async (ctx) =>
{
Console.WriteLine(ctx.Token);
},
OnTokenValidated = async (ctx) =>
{
Console.WriteLine("BreakPoint");
},
};
});
Directly use AddJwtBearer extension .
If using Azure AD v1.0 , you can click here for how to config the On-Behalf-Of flow applications include how to configure known client applications . Compare the request your application sent with the document shows . If using Azure AD v2.0 , you can check this document .
I'm using aspnet core 1.1 and Identity Server 4. I've created a policy in my client Startup.cs that denied all non-verified email accounts to use some sections of the website.
Here's the code of my policy:
//Add policies
services.AddAuthorization(authorizationOptions =>
{
authorizationOptions.AddPolicy(
ApplicationGlobals.Policy_HasValidatedAccount,
policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser();
policyBuilder.RequireClaim(JwtClaimTypes.EmailVerified, "true",
ClaimValueTypes.Boolean);
});
});
The question is: How can I refresh this EmailVerified claim AFTER the user a confirmed his account? The only way I found was to logout / login ...
If the information you are checking against is in the token, then yes the only way to get a new token is a new token request (aka authentication).
If you need something more dynamic, don't use data from a token.
https://leastprivilege.com/2016/12/16/identity-vs-permissions/
I'm doing this all within web pages via javascript.
First I send the user to Google so they can grant access:
https://accounts.google.com/o/oauth2/auth?response_type=token&scope=profile&redirect_uri=https://example.com/&client_id=1414xxxxxxxx-{myclientid}.apps.googleusercontent.com
After granting access they are redirected back to my site with something like this:
https://example.com/#access_token={their_token}&token_type=Bearer&expires_in=3600
Then I take that information and provide it to Amazon like so:
// Initialize the Amazon Cognito credentials provider
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:{my-pool-id}',
Logins: {
'accounts.google.com': "{their_token}"
}
});
AWS.config.region = 'us-east-1';
AWS.config.credentials.get(function(err) {
if ( err ) {
console.log(err);
}
else {
console.log("ID: "+identityId:AWS.config.credentials.identityId);
}
});
And there is where I always end up with an error in the console:
"Error: Invalid login token."
The identity pool 'us-east-1:{my-pool-id}' is setup in my Amazon Console with the Authentication provider 'Google+' setup and a Google Client ID matching the one in the google url (ie. 1414xxxxxxxx-{myclientid}.apps.googleusercontent.com).
I've also tried setting AccountId and RoleArn in the params to CognitoIdentityCredentials but it hasn't helped in this case. Am I using the Logins parameter correctly? What am I missing?
If I take out the Logins parameter or set it to an empty object, I do get an identityId which I assume would be associated with an unauthenticated role. How do I get an identity with an authenticated role using Google APIs as the token provider?
You need to use id_token instead of access_token. More details to obtain an id_token can be found in this documentation : OpenIDConnect