404使用OpenId Connect进行Apple身份验证后出错



采用scottbrady91.com,我正在尝试在我们的网站上进行苹果外部身份验证。我有一台微软的,但还没有苹果的。用户已被定向到appleid.apple.com,但经过身份验证后,它将返回到https://iluvrun.com/signin-apple(这是正确的(,但这没有得到处理,因此用户会得到404错误。

老实说,我不知道signin facebook、signin google或signin oidc是如何工作的,但它们确实是这样。所以我很难弄清楚为什么没有处理signin apple。

该网站是使用ASP.NET Web窗体生成的。以下是我在Startup.Auth.cs:

namespace ILR
{
public partial class Startup {
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions("Apple")
{
ClientId = "com.iluvrun.login",
Authority = "https://appleid.apple.com/auth/authorize",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
RedirectUri = "https://iluvrun.com/signin-apple",
PostLogoutRedirectUri = "https://iluvrun.com",
Scope = "name email",
ResponseType = OpenIdConnectResponseType.Code,
ResponseMode = OpenIdConnectResponseMode.FormPost,
CallbackPath = PathString.FromUriComponent("/signin-apple"),
Configuration = new OpenIdConnectConfiguration
{
AuthorizationEndpoint = "https://appleid.apple.com/auth/authorize",
TokenEndpoint = "https://appleid.apple.com/auth/token"
},
TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://appleid.apple.com",
IssuerSigningKey = new JsonWebKeySet(GetKeysAsync().Result).Keys[0]
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = (context) =>
{
context.TokenEndpointRequest.ClientSecret = TokenGenerator.CreateNewToken();
return Task.CompletedTask;
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
context.Response.Redirect("/Account/Login?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
},
ProtocolValidator = new OpenIdConnectProtocolValidator
{
RequireNonce = false,
RequireStateValidation = false
}
}
);
}
private static async Task<string> GetKeysAsync()
{
string jwks = await new HttpClient().GetStringAsync("https://appleid.apple.com/auth/keys");
return jwks;
}
}
public static class TokenGenerator
{
public static string CreateNewToken()
{
const string iss = "CHM57Z5A6";
const string aud = "https://appleid.apple.com";
const string sub = "com.iluvrun.login";
const string privateKey = "XXXX"; // contents of .p8 file
CngKey cngKey = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
JwtSecurityToken token = handler.CreateJwtSecurityToken(
issuer: iss,
audience: aud,
subject: new ClaimsIdentity(new List<Claim> { new Claim("sub", sub) }),
expires: DateTime.UtcNow.AddMinutes(5),
issuedAt: DateTime.UtcNow,
notBefore: DateTime.UtcNow,
signingCredentials: new SigningCredentials(new ECDsaSecurityKey(new ECDsaCng(cngKey)), SecurityAlgorithms.EcdsaSha256));
return handler.WriteToken(token);
}
}
}

有人知道我错过了什么吗?

您走在了正确的道路上,您的问题帮助我在项目中快速启动了自己的Apple ID OpenIdConnect OWIN集成解决方案。在这里找到你的帖子后,我花了很长时间才解决所有问题
使用您的代码后,我得到了相同的404错误。

  1. 404错误

这是由于CreateNewToken((方法中未处理的异常,该方法无法生成有效的令牌。在我的情况下,它缺少我的AppService的Azure配置,如CngKey.Import on Azure:中所述

WEBSITE_LOAD_USER_PROFILE = 1

在Azure中设置此配置后,我转到下一个问题:

  1. 未调用令牌端点

这是由于OpenIdConnectAuthenticationOptions:中缺少配置所致

RedeemCode = true

此选项触发OpenIdConnect内身份验证管道的所有下一步处理(TokenResponseReceived、SecurityTokenReceived、Security TokenValidated(

  1. AccountController.ExternalLoginCallback令牌处理问题

这很棘手。因为你只需要打电话给

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

正在获取:

loginInfo == null

因此,在阅读了许多关于这个主题的文章后,比如OWIN OpenID provider-GetExternalLoginInfo((返回null并尝试,最后唯一的解决方法是添加https://github.com/Sustainsys/owin-cookie-saver到我的Startup.cs,它修复了丢失令牌cookie的问题。它被标记为遗产,但这是我唯一的选择来解决这个问题。

因此,我的工作解决方案的最终OpenIdConnect选项配置是:

var appleIdOptions = new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "https://appleid.apple.com",
ClientId = "[APPLE_CLIENT_ID_HERE]",
Authority = "https://appleid.apple.com/auth/authorize",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
RedirectUri = "https://www.europeanart.eu/signin-apple",
PostLogoutRedirectUri = "https://www.europeanart.eu",
Scope = OpenIdConnectScope.Email,
RedeemCode = true,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
ResponseMode = OpenIdConnectResponseMode.FormPost,
CallbackPath = PathString.FromUriComponent("/signin-apple"),
Configuration = new OpenIdConnectConfiguration
{
AuthorizationEndpoint = "https://appleid.apple.com/auth/authorize",
TokenEndpoint = "https://appleid.apple.com/auth/token"
},
TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://appleid.apple.com",
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
IssuerSigningKeys = new JsonWebKeySet(GetKeys()).Keys,
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = (context) =>
{
var clientToken = JwtTokenGenerator.CreateNewToken();
logger.LogInfo("Apple: clientToken generated");
context.TokenEndpointRequest.ClientSecret = clientToken;
logger.LogInfo("Apple: TokenEndpointRequest ready");
return Task.FromResult(0);
},
TokenResponseReceived = (context) =>
{
logger.LogInfo("Apple: TokenResponseReceived");
return Task.FromResult(0);
},
SecurityTokenReceived = (context) =>
{
logger.LogInfo("Apple: SecurityTokenReceived");
return Task.FromResult(0);
},
SecurityTokenValidated = (context) =>
{
string userID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
logger.LogInfo("Apple: SecurityTokenValidated with userID=" + userID);
return Task.FromResult(0);
},
RedirectToIdentityProvider = (context) =>
{
logger.LogInfo("Apple: RedirectToIdentityProvider");
if(context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
logger.LogInfo("Apple: RedirectToIdentityProvider -> Authenticate()");
}
else if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Token)
{
logger.LogInfo("Apple: RedirectToIdentityProvider -> Token()");
}
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
logger.LogError("Apple Authentication Failed.", context.Exception);
context.Response.Redirect("/Account/Login?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
},
ProtocolValidator = new OpenIdConnectProtocolValidator
{
RequireNonce = false,
RequireStateValidation = false
}
};

最新更新