I have an OAuth2 token like this...
{{
"access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"expires_in": "3600",
"refresh_token": "xxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
}}
and I'm trying to create a DriveService object...
Service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "foo",
});
(like this?)
but I'm clearly not doing this properly and I'm having trouble finding documentation.
When I attempt to create a GoogleCredential to pass to the DriveService
GoogleCredential credential = GoogleCredential.FromJson(credentialAsSerializedJson).CreateScoped(GoogleDriveScope);
I get the following exception:
{System.InvalidOperationException: Error creating credential from JSON. Unrecognized credential type .
Am I going about this the wrong way entirely?
(This is the sample code context)
I have managed to figure this out.
The solution was to create a Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow with my ClientID and ClientSecret...
Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow googleAuthFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer()
{
ClientSecrets = new ClientSecrets()
{
ClientId = ClientID,
ClientSecret = ClientSecret,
}
});
and also a Google.Apis.Auth.OAuth2.Responses.TokenResponse:
Google.Apis.Auth.OAuth2.Responses.TokenResponse responseToken = new TokenResponse()
{
AccessToken = SavedAccount.Properties["access_token"],
ExpiresInSeconds = Convert.ToInt64(SavedAccount.Properties["expires_in"]),
RefreshToken = SavedAccount.Properties["refresh_token"],
Scope = GoogleDriveScope,
TokenType = SavedAccount.Properties["token_type"],
};
and use each to create a UserCredential that is, in turn, used to initialize the DriveService...
var credential = new UserCredential(googleAuthFlow, "", responseToken);
Service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "com.companyname.testxamauthgoogledrive",
});
I updated the TestXamAuthGoogleDrive test harness project to reflect these changes.
Related
I'd like to create an authentication/authorization flow of sorts using Identity Server to have a user authorize themselves in my Swagger API so that they may access endpoints marked with the [Authorize] attribute. This is the current flow I have:
I have Swagger set up with the NSwag middleware with the OAuth2 security scheme:
services.AddMvcCore().AddApiExplorer();
services.AddOpenApiDocument(settings =>
{
settings.Title = "MyProject Services";
settings.Version = "1.0";
settings.AddSecurity("oauth2", new NSwag.OpenApiSecurityScheme
{
Type = NSwag.OpenApiSecuritySchemeType.OAuth2,
Flow = NSwag.OpenApiOAuth2Flow.AccessCode,
AuthorizationUrl = "/connect/authorize",
TokenUrl = "/connect/token",
Scopes = new Dictionary<string, string>
{
{ "MyProjectServicesAPI", "API Access" }
}
});
settings.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("oauth2"));
});
And the OAuth2 client settings in Configure():
app.UseOpenApi();
app.UseSwaggerUi3(options =>
{
options.OAuth2Client = new NSwag.AspNetCore.OAuth2ClientSettings
{
ClientId = "MyProjectAPI",
ClientSecret = "mysecret",
UsePkceWithAuthorizationCodeGrant = true
};
});
After a user selects the scope and authorizes, they get redirected to my Identity Server Login Page I scaffolded and from there they can login. Once they put in their credentials and press, 'Login', they then get redirected back to the Swagger API. So far so good. Now this is where I start to have trouble cause I would like to later add policies so a user must have a specific claim to access an endpoint, but right now, I'm not able to see any of my user's claims in the JWT Bearer token that's in the request header when I access and endpoint. The only information I get about my user is in the 'sub' which is their GUID. I'd like to be able to get their username, email, and role(s) as well.
This is what I have setup for Identity Server so far (and where I'm currently stuck):
Under ConfigureServices():
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.IdentityResources = new IdentityResourceCollection
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource
{
Name = "roles",
DisplayName = "roles",
UserClaims = new List<string> { JwtClaimTypes.Role }
},
new IdentityResource
{
Name = "basicInfo",
DisplayName = "basic info",
UserClaims = new List<string> {
JwtClaimTypes.PreferredUserName
}
}
};
options.Clients = new ClientCollection
{
new Client
{
ClientId = "MyProjectAPI",
ClientName = "My Project Services API",
ClientSecrets = { new Secret("mysecret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "https://localhost:44319/swagger/oauth2-redirect.html" },
PostLogoutRedirectUris = { "https://localhost:44319/Identity/Account/Logout" },
AllowedScopes = {
"basicInfo",
"roles",
"MyProjectServicesAPI",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
RequirePkce = true,
RequireConsent = false
}
};
});
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerJwt()
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true
};
});
And then in the pipeline:
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
I recently got this error that's being thrown from Identity Server's OidcConfigurationController:
'Can't determine the type for the client 'MyProject''
I'm putting the Authorization Code type for the AllowedGrantTypes in my client so I'm not quite sure why it's throwing that error.
Do I need to be adding the claims to the Bearer token myself? If I'm including the scopes, why aren't those claims showing up? Thank you in advance for any assistance.
EDIT #1: I did resolve the error I was receiving from the OidcConfigurationController. I will add the JWT Bearer token only shows the 'MyProjectServicesAPI" scope and nothing else. However, my oidc discovery doc shows all of them?
I think I was able to partially solve my problem. So I didn't have Identity Server's Profile Service set up to grab my user's ID so it could grab the identity claims.
ProfileService.cs:
private readonly UserManager<ApplicationUser> _userManager;
public ProfileService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
// Add custom claims to access token.
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.IssuedClaims.AddRange(context.Subject.Claims);
var user = await _userManager.GetUserAsync(context.Subject);
var roles = await _userManager.GetRolesAsync(user);
var claims = new List<Claim>
{
new Claim(JwtClaimTypes.Email, user.Email),
new Claim(JwtClaimTypes.PreferredUserName, user.UserName),
};
foreach (var claim in claims)
{
context.IssuedClaims.Add(claim);
}
foreach (var role in roles)
{
context.IssuedClaims.Add(new Claim(JwtClaimTypes.Role, role));
}
}
public async Task IsActiveAsync(IsActiveContext context)
{
var user = await _userManager.GetUserAsync(context.Subject);
context.IsActive = (user != null) && user.LockoutEnabled;
}
And then back in Startup.cs:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
....
})
.AddProfileService<ProfileService>();
And that's it! Order does matter as I did have AddProfileService() before my AddApiAuthorization() and that didn't work. All of my scopes still aren't showing in my JWT token, so I will need to revisit that, even though the right claims are being pulled from those Identity resources.
I would like to use jwt tokens for authorization in my ASP.NET MVC website. I have already created an api that generates the jwt token from this tutorial :
https://www.c-sharpcorner.com/article/asp-net-web-api-2-creating-and-validating-jwt-json-web-token/
Now I have added the following nuget packages in my asp.net mvc website :
System.IdentityModel.Tokens.Jwt 5.5.0
Microsoft.Owin.Security.Jwt 4.0.1
Microsoft.AspNet.WebApi.Owin 5.2.3
Microsoft.Owin.Host.SystemWeb 4.0.1
And I have also created a startup file and inserted the following code:
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "example.com", //some string, normally web url,
ValidAudience = "example.com",
IssuerSigningKey = new
SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_secret_key_12345"))
}
});
I am then using postman to create a jwt token and challenge the website for authorization.
The generate token method is the following. (literally like the tutorial):
public Object GetToken()
{
string key = "my_secret_key_12345";
var issuer = "example.com"; //normally this will be your site URL
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Create a List of Claims, Keep claims name short
var permClaims = new List<Claim>();
permClaims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
permClaims.Add(new Claim("valid", "1"));
permClaims.Add(new Claim("userid", "1"));
permClaims.Add(new Claim("name", "bilal"));
//Create Security Token object by giving required parameters
var token = new JwtSecurityToken(issuer, //Issure
issuer, //Audience
permClaims,
expires: DateTime.Now.AddDays(1),
signingCredentials: credentials);
var jwt_token = new JwtSecurityTokenHandler().WriteToken(token);
return new { data = jwt_token };
}
I have created the following method to challenge the authorization:
[Authorize]
public string checkbystring()
{
return "worked";
}
But when I test it in postman, the following error keeps popping up:
IIS 10.0 Detailed Error - 401.0 - Unauthorized
Any suggestions to make this work would be highly appreciated.
I was facing a similar problem in ASP NET MVC, my token was generated, but when I used it I got the 401 error.
I needed to create an ASP NET MVC application, which used JWT token, but not Core.
The solution in my case was to include a library that was missing:
Microsoft.Owin.Host.SystemWeb
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Owin;
using System.Text;
[assembly: OwinStartup(typeof(WebAPI.Startup))]
namespace WebAPI
{
public class Startup
{
private readonly string SecuretyKey = "KEY--$%TESTE&##&#";
public void Configuration(IAppBuilder app)
{
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = "Teste.com",
ValidIssuer = "Teste.com",
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(SecuretyKey)),
ValidateLifetime = true,
ValidateIssuerSigningKey = true
}
});
}
}
}
In addition to it, the image of the other necessary packages follows.
enter image description here
I am developing some Web API with .NET Core 3.0 and want to integrate it with SwashBuckle.Swagger.
It is working fine, but when I add JWT authentication, it does not work as I expect.
To do that, I added the code below:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web API", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
});
After adding AddSecurityDefinition function, I can see the Authorize button and when I click it, I see the form below:
Then I type Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh. After doing it, I expect to see authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh in the request's header when I send a request to the Web API from Swagger, but authorization is not added to the request header. I am using SwashBuckle.Swagger(5.0.0-rc3). Please note there are many samples which work fine on .NET Core 2.0, but Swashbuckle swagger functions has changed on the latest version so I cannot use those samples.
After some research, I eventually found the answer here
Before seeing this page, I knew that I should use AddSecurityRequirement after AddSecurityDefinition because of many samples, but it was a problem that the function parameters have changed on .NET Core 3.0.
By the way, the final answer is as below:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "My API",
Version = "v1"
});
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
In = ParameterLocation.Header,
Description = "Please insert JWT with Bearer into field",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
});
If you are using Swagger 3.0 then it has build-in support for JWT authentication.
You need to use ParameterLocation.Header, SecuritySchemeType.Http, bearer, and JWT in OpenApiSecurityScheme as shown below.
After this, you wouldn't need to specify token in Bearer {token} format. Only specify the token and the security scheme will automatically apply it in the header.
// Bearer token authentication
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
Name = "Bearer",
BearerFormat = "JWT",
Scheme = "bearer",
Description = "Specify the authorization token.",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("jwt_auth", securityDefinition);
// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
Reference = new OpenApiReference()
{
Id = "jwt_auth",
Type = ReferenceType.SecurityScheme
}
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
{securityScheme, new string[] { }},
};
c.AddSecurityRequirement(securityRequirements);
In the accepted answer, "Bearer " is required to be written before the actual token.
A similar approach in which typing "Bearer " can be skipped is the following:
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Example API", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
In = ParameterLocation.Header,
Scheme = "bearer",
Description = "Please insert JWT token into field"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
Here, only pasting the JWT token is required for this to work.
Here's a solution updated for Swashbuckle.AspNetCore 5.3.2, integrated with IdentityServer4, with an API secured using a Bearer token.
In ConfigureServices() method:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
options.AddSecurityDefinition("Bearer", SecuritySchemes.BearerScheme(Configuration));
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{ SecuritySchemes.OAuthScheme, new List<string>() }
});
});
In Configure() method:
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/My.Api/swagger/v1/swagger.json", "My API V1");
options.OAuthClientId(Clients.TestClient);
options.OAuthAppName("My Api - Swagger");
options.OAuthClientSecret(Configuration["TestClientSecret"]);
});
internal static class SecuritySchemes
{
public static OpenApiSecurityScheme BearerScheme(IConfiguration config) => new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Description = "Standard authorisation using the Bearer scheme. Example: \"bearer {token}\"",
In = ParameterLocation.Header,
Name = "Authorization",
Scheme = "Bearer",
OpenIdConnectUrl = new System.Uri($"{config["TokenServerUrl"]}.well-known/openid-configuration"),
BearerFormat = "JWT",
Flows = new OpenApiOAuthFlows
{
Password = new OpenApiOAuthFlow
{
AuthorizationUrl = new System.Uri($"{config["TokenServerUrl"]}connect/authorize"),
Scopes = new Dictionary<string, string>
{
{ Scopes.Api, "My Api" }
},
TokenUrl = new System.Uri($"{config["TokenServerUrl"]}connect/token")
}
}
};
public static OpenApiSecurityScheme OAuthScheme => new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
};
}
If anyone is using NSwag and has landed here after searching the solution, here is the link from the official documentation.
NSwag Enable JWT authentication
PS: I know the original question was for SwashBuckle, but Google shows this link first when searching for NSwag as well.
If you don't want to add a token manually and you want the scopes to be selectable along with passing a clientId to the identity server you can add something like this.
I have used implicit flow, but you can configure any flow using the following mechanism:
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme()
{
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("http://localhost"),
TokenUrl = new Uri("http://localhost"),
Scopes = new Dictionary<string, string>
{
{ "Foundation API", "FoundationApi" }
}
}
},
In = ParameterLocation.Header,
Name = "Authorization",
Type = SecuritySchemeType.OAuth2
});
The output will be like this:
In Accept answer you have to manually append "bearer" with token, this will create new issues, Swagger can append "bearer" with token watch this following link
JWT Authentication and Swagger with .NET Core 3 and 5 YouTube video
I have the "Server application accessing a web API" scenario.
The web site uses OIDC and authenticates no problem.
However, I have a use case for accessing some of the web API without a user context and for that, I use client_credentials.
The server app has a client ID and the secret key.
So assume the web API URL is:
https://my-pc/WebService/api/my-api/
The web API has the RP identifier:
https://my-pc/WebService/api/my-api/
Access control policy is:
Permit everyone
I have one claim rule:
c:[] => issue(claim = c);
Client permissions is set to:
"All clients" with scope of openid and user_impersonation.
The code is:
AuthenticationContext ac = new AuthenticationContext("https://my-adfs/adfs/", false);
// ClientCredential contains client_id and secret key
AuthenticationResult result = await ac.AcquireTokenAsync("https://my-pc/WebService/api/my-api/", clientCredential);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://my-pc/WebService/api/my-api/");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("foo", "blah"), new KeyValuePair<string, string>("foo1", "blah1") });
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
ADFS returns the access token no problem but when I call the web api, I keep getting a 401 - Unauthenticated.
Any ideas?
Finally figured this out and wrote it up.
The two pieces of code:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
ClientCredential clientCredential = new ClientCredential(clientId, secretKey);
AuthenticationContext ac = new AuthenticationContext("https://my-adfs/adfs/", false);
AuthenticationResult result = await ac.AcquireTokenAsync("https://my-pc/WebService",
clientCredential);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
"https://my-pc/WebService/api/my-api/");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string,
string>("foo", "blah"), new KeyValuePair<string, string>("foo1", "blah1") });
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
// etc
And in Startup.Auth.cs
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters()
{
SaveSigninToken = true,
ValidAudience = "https://my-pc/WebService"
},
MetadataEndpoint = "https://my-adfs/FederationMetadata/2007-06/FederationMetadata.xml"
});
Took me a while!
Since you don't get the user principal in the access token, you have no user session attached to a principal. When the Web API looks for the principal in the cookie(or Authorization header if you're sending access token) it doesn't find the principal and you will still be an anonymous user.
I'm trying to implement a Google authentication in a MVC 5 web app. Authentication is working fine, but I would retrieve profile and picture informations.
To do this, I added a GoogleOAuth2AuthenticationOptions object to specify additional claims :
var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
{
ClientId = "xxxxxxxxxxxxxxxx",
ClientSecret = "xxxxxxxxxxxxxxxxx",
CallbackPath = new PathString("/Account/LoginCallback"),
Provider = new GoogleOAuth2AuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
}
}
};
app.UseGoogleAuthentication(googleOAuth2AuthenticationOptions);
But it causes that a wrong URL is generated :
http://admin.localhost.com/Account/LoginCallback&state=Gs-otJmI79bgWA3_qJzDcGziWnkRCOf7JRoCUDCIz0jv4IIvDdoZlZzVSq2kZxfaPFDmv9hbZGp5q1Aq8mpLPguKnCF31twHj8NQCMv_NrgZzvKwaelmZr_HwY_bdj8h1ICFrkGTKLJ1saEYDbFJ2CJxvDkyBL2iygQmTXQTs-aUiL4yWe5_7dZQOjP_mDUSW-GXns3wr7Okwkoj8VEITJTUz9nAbrBd_N_7puTMlHU&client_id=xxxxxxxxxxxxxxxx
There is no '?' before parameters, that's cause a redirect_uri_mismatch.
However, when I use simply :
app.UseGoogleAuthentication(
clientId : "xxxxxxxxxxxxxxxxxxx",
clientSecret : "xxxxxxxxxxxxxxxxx");
It's working.
Any idea ?
Use only this much.
var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
{
ClientId = "MYCLIENTID",
ClientSecret = "MYSECRET",
};
app.UseGoogleAuthentication(googleOAuth2AuthenticationOptions);
This method seems to automatically use the signin-google request in the address.To fix this change google callback location in the google console to point to this address.
Add RouteConfig file
routes.MapRoute( name: "signin-google", url: "signin-google", defaults: new { controller = "Account", action = "LoginCallback" } );
Use this Below Code Snippet which is working fine just replace ClientID and ClientSecret will work for you.
var googleOptions = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
Provider = new GoogleOAuth2AuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name)));
context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email)));
//This following line is need to retrieve the profile image
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:google:accesstoken", context.AccessToken, ClaimValueTypes.String, "Google"));
return Task.FromResult(0);
}
}
};
app.UseGoogleAuthentication(googleOptions);
if still error exists
Assume if your application URI is as shown below
http://localhost:2625/
Then at console.developers.google.com the URI you have registered need to be changed as show below.
Just add [signin-google] in URI at end
http://localhost:2625/signin-google
And finally save it.