[英]Authentication with Google in Web API and Swagger
I have integrated a Web API c# app with Swagger.我已将 Web API c# 应用程序与 Z336FF1E9AA6177EA7A71984FA8C241BZ 集成。 I have already implemented AAD authentication which is working fine.我已经实现了工作正常的 AAD 身份验证。 Now I want to add Google authentication.现在我想添加谷歌身份验证。 I have done code as below.我已经完成了如下代码。
SwaggerConfig.cs SwaggerConfig.cs
c.OAuth2("oauth2")
.Description("Google Auth")
.Flow("implicit")
.AuthorizationUrl($"https://accounts.google.com/o/oauth2/v2/auth")
.Scopes(scopes => scopes.Add("openid", "Sign you in permission"));
Startup.cs启动.cs
app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
googleAuthOptions = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
ClientSecret = "xxxxxxxxxxxxxxxxxxxx",
};
app.UseGoogleAuthentication(googleAuthOptions);
I get authorized from google login screen and successfully redirected back to the UI.我从谷歌登录屏幕获得授权并成功重定向回用户界面。 But when I try to access any method, I get 401 Unauthorized error even bearer token is there.但是当我尝试访问任何方法时,我得到 401 Unauthorized 错误,即使不记名令牌在那里。
After authenticating with google谷歌认证后
I know I haven't verified the access token in the Startup.cs file because I have lack of knowledge.我知道我没有验证 Startup.cs 文件中的访问令牌,因为我缺乏知识。 I have gone through few articles with complex implementation but I want to achieve this in a simplest way.我已经阅读了几篇具有复杂实现的文章,但我想以最简单的方式实现这一目标。 Below code works for AAD without any further code verification.以下代码适用于 AAD,无需任何进一步的代码验证。
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new Microsoft.Owin.Security.ActiveDirectory.WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = Settings.AzureADTenant,
TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = new string[] { Settings.AzureADAudience, Settings.AzureAppURI },
ValidIssuers = new string[] {
$"https://sts.windows.net/{Settings.AzureADTenant}/",
$"https://login.microsoftonline.com/{Settings.AzureADTenant}/v2.0"
}
}
});
The token you're getting is an access token, the problem is that swagger by default makes the token request with the response_type parameter as token instead of token id_token.您获得的令牌是访问令牌,问题是 swagger 默认使用 response_type 参数作为令牌而不是令牌 id_token 发出令牌请求。
You could authenticate with google from swagger following the below steps:您可以按照以下步骤从 swagger 向 google 进行身份验证:
In your wwwroot folder (if you don't have one, you can create it), create a JS file with the following content在你的 wwwroot 文件夹中(如果没有,可以创建),创建一个 JS 文件,内容如下
window.swaggerUiAuth = window.swaggerUiAuth || {}; window.swaggerUiAuth.tokenName = 'id_token'; if (.window.isOpenReplaced) { window.open = function (open) { return function (url) { url = url,replace('response_type=token'; 'response_type=token id_token'). return open,call(window; url); }. }(window;open). window;isOpenReplaced = true; }
Once that's done, in your Configure method add the following:完成后,在您的配置方法中添加以下内容:
app.UseSwaggerUI(c => { //your additional stuff... c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> {{ "nonce", "anyNonceStringHere" }}); c.OAuthClientId(this.oauth2Config.ClientId); c.InjectJavascript("YourJustCreatedJSFileName.js"); });
Now in your AddSwaggerGen builder, add the security definition and the security requirements.现在在您的 AddSwaggerGen 构建器中,添加安全定义和安全要求。 (You can split it in methods just to make it cleaner). (您可以将其拆分为方法以使其更清洁)。
//in your ConfigureServices services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "wellship_svc_app", Version = "v1" }); this.AddSwaggerOAuth2Configuration(c); });
Create this private method in your startup class.在您的启动 class 中创建此私有方法。 Note the extensions property in the security scheme using the id_token instead of the access token.请注意使用 id_token 而不是访问令牌的安全方案中的扩展属性。
private void AddSwaggerOAuth2Configuration(SwaggerGenOptions swaggerGenOptions)
{
var securityScheme = new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows()
{
Implicit = new OpenApiOAuthFlow()
{
AuthorizationUrl = new Uri("https://accounts.google.com/o/oauth2/v2/auth"),
Scopes = new Dictionary<string, string> {{"email", "email"}, {"profile", "profile"}}
}
},
Extensions = new Dictionary<string, IOpenApiExtension>
{
{"x-tokenName", new OpenApiString("id_token")}
},
};
swaggerGenOptions.AddSecurityDefinition("Bearer", securityScheme) ;
var securityRequirements = new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new List<string> {"email", "profile"}
}
};
swaggerGenOptions.AddSecurityRequirement(securityRequirements);
}
public class GoogleTokenValidator : ISecurityTokenValidator
{
private readonly JwtSecurityTokenHandler _tokenHandler;
public GoogleTokenValidator()
{
_tokenHandler = new JwtSecurityTokenHandler();
}
public bool CanValidateToken => true;
public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;
public bool CanReadToken(string securityToken)
{
return _tokenHandler.CanReadToken(securityToken);
}
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
validatedToken = null;
var payload = GoogleJsonWebSignature.ValidateAsync(securityToken, new GoogleJsonWebSignature.ValidationSettings()).Result;
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, payload.Name),
new (ClaimTypes.Name, payload.Name),
new (JwtRegisteredClaimNames.FamilyName, payload.FamilyName),
new (JwtRegisteredClaimNames.GivenName, payload.GivenName),
new (JwtRegisteredClaimNames.Email, payload.Email),
new (JwtRegisteredClaimNames.Sub, payload.Subject),
new (JwtRegisteredClaimNames.Iss, payload.Issuer)
};
try
{
var principle = new ClaimsPrincipal();
principle.AddIdentity(new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme));
return principle;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.IncludeErrorDetails = true;
o.SecurityTokenValidators.Clear();
o.SecurityTokenValidators.Add(new GoogleTokenValidator());
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.