【问题标题】:Authentication Settings for Amazon and EvernoteAmazon 和 Evernote 的身份验证设置
【发布时间】:2019-04-28 18:26:03
【问题描述】:

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

脸书

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 的设置?

【问题讨论】:

  • Configuration["auth:facebook:appid"]; 所做的只是告诉应用在您的appsettings.json 或该路径的其他配置文件中查找,然后返回该值。所以你仍然需要从每个服务中获取一个 clientId 和 secret,为此你必须访问他们的网站并了解他们的 API。例如,我经常使用 Google .我会假设亚马逊和印象笔记是一样的。 docs.microsoft.com/en-us/aspnet/core/security/authentication/…
  • 感谢您的评论,完全了解从配置中读取的客户端ID和机密。我的问题更多的是有人知道 Evernote 和 Amazon 的设置是什么吗?正如您可能猜到的那样……没有 .AddAmazon 或 .AddEvernote 扩展方法,我假设我需要使用通用的 AddOpenIdConnect 方法并为其提供正确的配置。有人知道这些设置是什么吗?

标签: c# oauth-2.0 asp.net-identity identityserver4


【解决方案1】:

您可以找到 Login with Amazon 参考 here
Amazon 仍然不支持 OIDC,但支持 OAuth。但是,dotnet 的默认 OAuthHandler 不提供 UserInfoEndpoint 处理。这就是为什么您必须实现对UserInfoEndpoint 的调用(可以从 oidc 获取它)或破解 OIDC 以使其认为它有 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();
       }
  };
})

【讨论】:

    【解决方案2】:

    很遗憾,Login with Amazon 和 Evernote 都不支持 Open ID Connect。其他提到的服务都可以,可以通过访问每个服务的相应配置站点来验证:GoogleMicrosoft

    还有一些其他的没有在 .Net 中预先配置并且可以与它一起使用: Salesforce

    您可能已经注意到,Open ID Connect 的配置通常存储在带有“/.well-known/openid-configuration”后缀的站点上。这称为 OpenID Connect 元数据文档,它包含应用程序进行登录所需的大部分信息。这包括诸如要使用的 URL 和服务的公共签名密钥的位置等信息。

    现在让我们为自定义 Open ID Connect 提供商进行 .Net 配置(我将使用 Salesforce,因为它支持 Open ID):

    services.AddAuthentication()
    .AddFacebook(options =>
    {
        options.AppId = Configuration["auth:facebook:appid"];
        options.AppSecret = Configuration["auth:facebook:appsecret"];
    })
    .AddOpenIdConnect("OpenIdConnectSalesforce", "Salesforce", options =>
    {
        options.Authority = "https://login.salesforce.com";
        options.ClientId = Configuration["auth:salesforce:appid"];
        options.ClientSecret = Configuration["auth:salesforce:appsecret"];
        options.ResponseType = "code";
    });
    

    启动网络应用程序后,我们可以看到使用 Salesforce 登录的附加按钮:

    对于 Evernote 和 Amazon,您可以分别使用它们的 SDK 和 API 来实现它们的登录方法。我相信他们支持 OAuth。

    【讨论】:

      【解决方案3】:

      通过@d-f 扩展解决方案以使用 OAuth 处理程序。

      .AddOAuth("lwa-oauth", "OauthLoginWithAmazon", options =>
      {
          options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
      
          options.ClientId = "amzn1.application-oa2-client.zzzzzzzzzzzz";
          options.ClientSecret = "4c0630b4166c901519a730835ezzzzzzzzzzzzzzzz";
          options.SaveTokens = true;
          options.CallbackPath = "/signin-amazon";
          options.Scope.Clear();
          options.Scope.Add("profile");
      
          options.AuthorizationEndpoint = "https://www.amazon.com/ap/oa";
          options.TokenEndpoint = "https://api.amazon.com/auth/o2/token";
          options.UserInformationEndpoint = "https://api.amazon.com/user/profile";
      
          options.Events = new OAuthEvents
          {
               OnCreatingTicket = async context =>
               {
                  var accessToken = context.AccessToken;
                  HttpResponseMessage responseMessage = 
                       await context.Backchannel.SendAsync(
                              new HttpRequestMessage(HttpMethod.Get, options.UserInformationEndpoint)
                  {
                    Headers = 
                    {
                          Authorization = new AuthenticationHeaderValue("Bearer", accessToken)
                    }
                  });
                  responseMessage.EnsureSuccessStatusCode();
                  string userInfoResponse = await responseMessage.Content.ReadAsStringAsync();
                  var user = JObject.Parse(userInfoResponse);
                  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();
             }
         };
      })
      

      【讨论】:

        猜你喜欢
        • 2011-01-01
        • 2015-08-26
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        • 2020-11-11
        • 1970-01-01
        • 2015-11-05
        • 1970-01-01
        相关资源
        最近更新 更多