写好参数通过Config 配置到 sitecore pipeline 即可
public class OpenIdIdentityProvider : IdentityProvidersProcessor
{
protected override string IdentityProviderName => OpenIdModel.IdentityProvider;
public OpenIdIdentityProvider(FederatedAuthenticationConfiguration federatedAuthenticationConfiguration, ICookieManager cookieManager, BaseSettings settings) : base(federatedAuthenticationConfiguration, cookieManager, settings)
{
}
protected override void ProcessCore(IdentityProvidersArgs args)
{
Assert.ArgumentNotNull(args, nameof(args));
try
{
IdentityProvider identityProvider = GetIdentityProvider();
string authenticationType = GetAuthenticationType();
string prefix = Settings.GetSetting(OpenIdModel.OpenIdPrefix);
string clientId = Settings.GetSetting(OpenIdModel.ClientId);
string authority = $"{Sitecore.StringUtil.EnsurePostfix('/', prefix)}{Settings.GetSetting(OpenIdModel.AuthorizeEndpoint)}";
string metaAddress = Settings.GetSetting(OpenIdModel.MetaAddress);
string redirectUri = Settings.GetSetting(OpenIdModel.RedirectURI);
string logout = Settings.GetSetting(OpenIdModel.PostLogoutRedirectURI);
var options = new OpenIdConnectAuthenticationOptions(authenticationType)
{
Caption = identityProvider.Caption,
AuthenticationType = authenticationType,
AuthenticationMode = AuthenticationMode.Passive,
ResponseType = OpenIdConnectResponseType.Code,
ClientId = clientId,
CookieManager = CookieManager,
MetadataAddress = metaAddress,
RedirectUri = redirectUri,
Authority = authority,
UseTokenLifetime = true,
RedeemCode = true,
SaveTokens = true,
Scope = $"{OpenIdConnectScope.OpenIdProfile} {clientId}",
ResponseMode = OpenIdConnectResponseMode.Query,
PostLogoutRedirectUri = logout,
TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name" },
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = context =>
{
if (context.ProtocolMessage.RequestType.Equals(OpenIdConnectRequestType.Authentication))
{
string codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (SHA256 sha256 = SHA256.Create())
{
byte[] challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
context.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
context.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
RememberCodeVerifier(context, codeVerifier);
}
return Task.CompletedTask;
},
AuthorizationCodeReceived = context =>
{
// 验证通过,收到code 和state,触发这里的logic, 这里写上,自动呼叫获取id_token 的logic
Helper.Logger.Info($"AuthorizationCodeReceived");
string codeVerifier = RetrieveCodeVerifier(context);
context.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
//context.AuthenticationTicket.Identity.ApplyClaimsTransformations(new TransformationContext(FederatedAuthenticationConfiguration, identityProvider));
return Task.CompletedTask;
},
SecurityTokenValidated = context =>
{
//收到最终我们需要的id_token时,触发这里
Helper.Logger.Info($"SecurityTokenValidated");
context.AuthenticationTicket.Identity.ApplyClaimsTransformations(new TransformationContext(FederatedAuthenticationConfiguration, identityProvider));
return Task.CompletedTask;
},
AuthenticationFailed = context =>
{
Helper.Logger.Info($"AuthenticationFailed");
context.HandleResponse();
Helper.Logger.Error(context.Exception.ToString(), context.Exception);
context.Response.Redirect(logout);
return Task.FromResult(0);
},
SecurityTokenReceived = context =>
{
Helper.Logger.Info($"SecurityTokenReceived");
return Task.CompletedTask;
},
}
};
args.App.UseOpenIdConnectAuthentication(options);
}
catch (Exception ex)
{
Helper.Logger.Error(ex.ToString(), ex);
}
}
private void RememberCodeVerifier(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context, string codeVerifier)
{
var properties = new AuthenticationProperties();
properties.Dictionary.Add("cv", codeVerifier);
context.Options.CookieManager.AppendResponseCookie(
context.OwinContext,
GetCodeVerifierKey(context.ProtocolMessage.State),
Convert.ToBase64String(Encoding.UTF8.GetBytes(context.Options.StateDataFormat.Protect(properties))),
new CookieOptions
{
HttpOnly = true,
Secure = context.Request.IsSecure,
Expires = DateTime.UtcNow + context.Options.ProtocolValidator.NonceLifetime
});
}
private string RetrieveCodeVerifier(AuthorizationCodeReceivedNotification context)
{
string key = GetCodeVerifierKey(context.ProtocolMessage.State);
string codeVerifierCookie = context.Options.CookieManager.GetRequestCookie(context.OwinContext, key);
if (codeVerifierCookie != null)
{
CookieOptions cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = context.Request.IsSecure
};
context.Options.CookieManager.DeleteCookie(context.OwinContext, key, cookieOptions);
}
AuthenticationProperties cookieProperties = context.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
cookieProperties.Dictionary.TryGetValue("cv", out var codeVerifier);
return codeVerifier;
}
private string GetCodeVerifierKey(string state)
{
using (var hash = SHA256.Create())
return $"{OpenIdConnectAuthenticationDefaults.CookiePrefix}cv.{Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(state)))}";
}
}
config 如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:environment="http://www.sitecore.net/xmlconfig/environment/">
<sitecore>
<sc.variable name="OpenIdTenant" value="xxxx" /> <!-- your data -->
<sc.variable name="OpenIdSignInUpPage" value="xxxx" /> <!-- your data -->
<settings>
<setting name="OpenIdPrefix" value="$(OpenIdTenant)/$(OpenIdSignInUpPage)/oauth2/v2.0" />
<setting name="ClientId" value="xxxx" /> <!-- your data -->
<setting name="MetaAddress" value="$(OpenIdTenant)/$(OpenIdSignInUpPage)/v2.0/.well-known/openid-configuration" />
<setting name="AuthorizeEndpoint" value="authorize" />
<setting name="TokenEndpoint" value="token" />
<setting name="LogoutEndpoint" value="logout" />
<setting name="PostLogoutRedirectURI" value="xxxx" /> <!-- your data -->
<setting name="RedirectURI" value="xxxxx" /> <!-- your data -->
</settings>
<pipelines>
<owin.identityProviders>
<processor type="namespance.className, dll Name" resolve="true" />
</owin.identityProviders>
</pipelines>
<federatedAuthentication>
<identityProviders hint="list:AddIdentityProvider">
<identityProvider id="OpenId" type="Sitecore.Owin.Authentication.Configuration.DefaultIdentityProvider, Sitecore.Owin.Authentication">
<param desc="name">$(id)</param>
<param desc="domainManager" type="Sitecore.Abstractions.BaseDomainManager" resolve="true" />
<caption>Sign-in with Open Id</caption>
<!-- Update your domain if not default -->
<domain>extranet</domain>
<icon>/sitecore/shell/themes/standard/Images/24x24/msazure.png</icon>
<transformations hint="list:AddTransformation">
<transformation name="idp" value="OpenId" type="Sitecore.Owin.Authentication.Services.SetIdpClaimTransform, Sitecore.Owin.Authentication" />
</transformations>
</identityProvider>
</identityProviders>
<propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication">
<maps hint="list" resolve="true">
<map name="Email claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
<data hint="raw:AddData">
<source name="Email" />
<target name="Email" />
</data>
</map>
<map name="Display name claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
<data hint="raw:AddData">
<source name="name" />
<target name="FullName" />
</data>
</map>
</maps>
</propertyInitializer>
<identityProvidersPerSites>
<mapEntry name="all" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication" resolve="true">
<sites hint="list" resolve="true">
<site>website</site>
</sites>
<identityProviders hint="list:AddIdentityProvider">
<identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='OpenId']" />
</identityProviders>
<externalUserBuilder type="Sitecore.Owin.Authentication.Services.DefaultExternalUserBuilder, Sitecore.Owin.Authentication" resolve="true">
<IsPersistentUser>false</IsPersistentUser>
</externalUserBuilder>
</mapEntry>
</identityProvidersPerSites>
</federatedAuthentication>
</sitecore>
</configuration>
呼叫 sign in or up 接口
[HttpPost]
public ActionResult OnePass()
{
string idp = "xxx"; // 对应config的id
BaseCorePipelineManager corePipelineManager = DependencyResolver.Current.GetService<BaseCorePipelineManager>();
GetSignInUrlInfoArgs args = new GetSignInUrlInfoArgs(Sitecore.Context.Site.Name, "/"); //Settings.GetAppSetting("RedirectURI")
GetSignInUrlInfoPipeline.Run(corePipelineManager, args);
//Get link to IDP
var redirectToIdp = args.Result.FirstOrDefault(z => z.IdentityProvider.Equals(idp, StringComparison.OrdinalIgnoreCase)).Href;
PostRedirect(redirectToIdp);
return null;
}
private void PostRedirect(string url)
{
//For security, Login required form post method
Response.Clear();
var sb = new System.Text.StringBuilder();
sb.Append("<html>");
sb.AppendFormat("<body οnlοad='document.forms[0].submit()'>");
sb.AppendFormat("<form action='{0}' method='post'>", url);
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");
Response.Write(sb.ToString());
Response.End();
}