I am trying to implement Google Account As Open ID Connect Identity Provider using .Net according following links provided by google:
I added the following in Startup/Program.cs:
var configurationGoogle = new OpenIdConnectConfiguration()
{
Issuer = "https://accounts.google.com",
AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth",
TokenEndpoint = "https://oauth2.googleapis.com/token",
UserInfoEndpoint = "https://openidconnect.googleapis.com/v1/userinfo",
JwksUri = "https://www.googleapis.com/oauth2/v3/certs",
RegistrationEndpoint = "https://oauth2.googleapis.com/revoke",
};
builder.Services.AddAuthentication(options =>
{
// options.DefaultSignInScheme = "Cookies";
// options.DefaultAuthenticateScheme = "Cookies";
// options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie().AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme,
options =>
{
// options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
// {
// RequireExpirationTime = false,
// ValidateLifetime = false,
// RequireSignedTokens = false,
// ValidateIssuerSigningKey = false,
// ValidateAudience = false,
// ValidateIssuer = false,
// RequireAudience = false,
// };
options.ClientId = "********.apps.googleusercontent.com";
options.ClientSecret = "******";
options.Configuration = configurationGoogle;
options.SignInScheme = "Cookies";
options.CallbackPath = new PathString("/signin-google");
options.Scope.Add("openid");
options.Scope.Add("email");
options.Scope.Add("profile");
options.SaveTokens = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.Events.OnAuthorizationCodeReceived = ctx =>
{
Console.WriteLine(@"Code:{0}", ctx.ProtocolMessage.Code);
return Task.CompletedTask;
};
options.Events.OnTokenResponseReceived = ctx =>
{
Console.WriteLine("I am executing!");
Console.WriteLine(@"Access Token:{0}", ctx.TokenEndpointResponse.AccessToken);
List<AuthenticationToken> tokens = ctx.Properties!.GetTokens().ToList();
tokens.Add(new AuthenticationToken()
{
Name = "TicketCreated",
Value = DateTime.UtcNow.ToString()
});
tokens.Add(new AuthenticationToken()
{
Name = "access_token",
Value = ctx.TokenEndpointResponse.AccessToken,
});
tokens.Add(new AuthenticationToken()
{
Name = "refresh_token",
Value = ctx.TokenEndpointResponse.RefreshToken,
});
ctx!.Properties!.StoreTokens(tokens);
return Task.CompletedTask;
};
options.Events.OnUserInformationReceived = ctx =>
{
Console.WriteLine(ctx.User);
return Task.CompletedTask;
};
}
);
And then try to challange it and after redirection it give me following error:
An unhandled exception occurred while processing the request.
SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match key:
kid: 'System.String'.
Exceptions caught:
'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.
Microsoft.IdentityModel.Tokens.InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt(SecurityToken securityToken, Nullable<DateTime> notBefore, Nullable<DateTime> expires, string kid, TokenValidationParameters validationParameters, StringBuilder exceptionStrings)
As I think, we use code in OIDC and we do not require to verify token (which we have not it but we have access_token here instead!) and only in OAuth 2.0 we should validate it. But it gave me error by the way. Where I am wrong in this procedure here? It should be noticed that I am getting both access_token and refresh_token and also code in OnTokenResponseReceived event and if it not throw error I can do my Authentication Procedure according to Open ID Connect and then persist them with Cookies for next use.How I can prevent this error and Does I am correct regard to OpenIDConnect that we may not verify tokens?!
The OpenID Connect has an ID Token which requires validation. According to OpenID specification we should validate it using RS256 algorithm which requires a public key from issuer. This public key Id should get from
JwksUrifor kid specified in ID Token Header. This step do automatically in case of using metadata in OIDC options. But in case of using Configuration as we do in this question, we should specify this keys manually in Option Token Validation Parameters as below:We also can do it more dynamicly in option Events as below:
Where
GoogleKeysis a class defined as below: