首页 > 解决方案 > Amazon 和 Evernote 的身份验证设置

问题描述

如果您参考https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.2可以看到可以配置 OpenID Connect (OIDC)各种提供者的身份验证如下:

Facebook

services.AddAuthentication()
        .AddFacebook(options =>
        {
            options.AppId = Configuration["auth:facebook:appid"];
            options.AppSecret = Configuration["auth:facebook:appsecret"];
        });

谷歌

services.AddAuthentication()
        .AddGoogle(options =>
        {
            options.ClientId = Configuration["auth:google:clientid"];
            options.ClientSecret = Configuration["auth:google:clientsecret"];
        });

微软

services.AddAuthentication()
        .AddMicrosoftAccount(options =>
        {
            options.ClientId = Configuration["auth:microsoft:clientid"];
            options.ClientSecret = Configuration["auth:microsoft:clientsecret"];
        });

我的问题是,有没有人需要我提供支持 Amazon 和 Evernote OIDC 的设置?

标签: c#oauth-2.0asp.net-identityidentityserver4

解决方案


你可以在这里找到 Login with Amazon 参考
Amazon 仍然不支持 OIDC,但支持 OAuth。但是,dotnet 的默认设置OAuthHandler不提供UserInfoEndpoint处理。这就是为什么您必须实现对UserInfoEndpoint(可以从 oidc 获取)的调用或破解 OIDC 以使其在没有 id_token 时认为它具有 id_token 的原因。我已经通过了第二条路线。有点肮脏的把戏,但我已经确定了我的用户。

.AddOpenIdConnect("lwa", "LoginWithAmazon", options =>
{
  options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
  options.SignOutScheme = IdentityServerConstants.SignoutScheme;

  options.Authority = "https://www.amazon.com/";
  options.ClientId = "amzn1.application-oa2-client.xxxxxxxxxxxxxx";
  options.ClientSecret = "xxxxxxxxxxxxxxxxx";
  options.ResponseType = "code";
  options.ResponseMode = "query";
  options.SaveTokens = true;
  options.CallbackPath = "/signin-amazon";
  options.SignedOutCallbackPath = "/signout-callback-amazon";
  options.RemoteSignOutPath = "/signout-amazon";
  options.Scope.Clear();
  options.Scope.Add("profile");
  options.GetClaimsFromUserInfoEndpoint = true;

  var rsa = RSA.Create();
  var key = new RsaSecurityKey(rsa){KeyId = "1"};

  var jwtClaims = new List<Claim>
                    {
                        new Claim(JwtClaimTypes.IssuedAt, "now"),
                        new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString()),
                        new Claim(JwtClaimTypes.Subject, Guid.NewGuid().ToString())
                    };

  var jwt = new JwtSecurityToken(
                    "issuer",
                    "audience",
                    jwtClaims,
                    DateTime.UtcNow,
                    DateTime.UtcNow.AddHours(1),
                    new SigningCredentials(key, "RS256"));

  var handler = new JwtSecurityTokenHandler();
  handler.OutboundClaimTypeMap.Clear();
  var token = handler.WriteToken(jwt);

  options.Configuration = new OpenIdConnectConfiguration
  {
      AuthorizationEndpoint = "https://www.amazon.com/ap/oa",
      TokenEndpoint = "https://api.amazon.com/auth/o2/token",
      UserInfoEndpoint = "https://api.amazon.com/user/profile"
  };

  options.TokenValidationParameters = new TokenValidationParameters
  {
      ValidateTokenReplay = false,
      ValidateIssuer = false,
      ValidateAudience = false,
      ValidateLifetime = false,
      IssuerSigningKey = key
  };

  AuthorizationCodeReceivedContext hook = null;
  options.Events = new OpenIdConnectEvents
  {
       OnAuthenticationFailed = async context =>
       {
           //context.SkipHandler();
       },
       OnAuthorizationCodeReceived = async context => { hook = context; },
       OnTokenResponseReceived = async context =>
       {
           context.TokenEndpointResponse.IdToken = token;
           hook.TokenEndpointResponse = context.TokenEndpointResponse;
       },
       OnUserInformationReceived = async context =>
       {
           var user = context.User;
           var claims = new[]
           {
               new Claim(JwtClaimTypes.Subject, user["user_id"].ToString()),
               new Claim(JwtClaimTypes.Email, user["email"].ToString()),
               new Claim(JwtClaimTypes.Name, user["name"].ToString())
           };
           context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims));
           context.Success();
       }
  };
})

推荐阅读