您获得的令牌是访问令牌,问题是默认情况下,swagger 使用 response_type 参数作为令牌而不是令牌 id_token 发出令牌请求。
您可以按照以下步骤从 swagger 向 google 进行身份验证:
-
在你的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;
}
-
完成后,在您的 Configure 方法中添加以下内容:
app.UseSwaggerUI(c =>
{
//your additional stuff...
c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> {{ "nonce", "anyNonceStringHere" }});
c.OAuthClientId(this.oauth2Config.ClientId);
c.InjectJavascript("YourJustCreatedJSFileName.js");
});
-
现在在您的 AddSwaggerGen 构建器中,添加安全定义和安全要求。 (您可以将其拆分为多个方法以使其更简洁)。
//in your ConfigureServices
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "wellship_svc_app", Version = "v1" });
this.AddSwaggerOAuth2Configuration(c);
});
在你的启动类中创建这个私有方法。请注意使用 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;
}
}
}
- 使用您的自定义 google 验证器类验证您的令牌:
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());
});