Security源碼解析系列介紹了微軟提供的各類認證架構,其中OAuth2.0,OpenIdConnect屬於遠程認證架構,所謂遠程認證,是指token的頒發是由另外的站點實現的。html
IdentityServer4是基於OpenIdConnect協議的認證中心框架,可以幫助咱們搭建中心化的認證服務。ios
能夠將OpenIdConnect協議當即理解成需求文檔,idsv4基於需求提供了一系列的api。git
對於idsv還不太瞭解的能夠看下面的資料,本系列主要學習梳理idsv的源碼,結合協議加深理解。github
曉晨姐姐系列文章api
官方文檔cookie
項目地址以下app
克隆到本地,項目結構如圖
核心項目是IdentityServer4,其他的都是與微軟框架集成、以及處理持久化的項目。
項目結構如圖。Endpoints文件夾就是接口文件,咱們先看下依賴注入、中間件的代碼,而後看下每一個接口。
public static IIdentityServerBuilder AddIdentityServer(this IServiceCollection services) { var builder = services.AddIdentityServerBuilder(); builder .AddRequiredPlatformServices() .AddCookieAuthentication() .AddCoreServices() .AddDefaultEndpoints() .AddPluggableServices() .AddValidators() .AddResponseGenerators() .AddDefaultSecretParsers() .AddDefaultSecretValidators(); // provide default in-memory implementation, not suitable for most production scenarios builder.AddInMemoryPersistedGrants(); return builder; }
public static IIdentityServerBuilder AddRequiredPlatformServices(this IIdentityServerBuilder builder) { builder.Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddOptions(); builder.Services.AddSingleton( resolver => resolver.GetRequiredService<IOptions<IdentityServerOptions>>().Value); builder.Services.AddHttpClient(); return builder; }
public static IIdentityServerBuilder AddCookieAuthentication(this IIdentityServerBuilder builder) { builder.Services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme) .AddCookie(IdentityServerConstants.DefaultCookieAuthenticationScheme) .AddCookie(IdentityServerConstants.ExternalCookieAuthenticationScheme); builder.Services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, ConfigureInternalCookieOptions>(); builder.Services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureInternalCookieOptions>(); builder.Services.AddTransientDecorator<IAuthenticationService, IdentityServerAuthenticationService>(); builder.Services.AddTransientDecorator<IAuthenticationHandlerProvider, FederatedSignoutAuthenticationHandlerProvider>(); return builder; }
/// <summary> /// Adds the core services. /// </summary> /// <param name="builder">The builder.</param> /// <returns></returns> public static IIdentityServerBuilder AddCoreServices(this IIdentityServerBuilder builder) { builder.Services.AddTransient<SecretParser>(); builder.Services.AddTransient<SecretValidator>(); builder.Services.AddTransient<ScopeValidator>(); builder.Services.AddTransient<ExtensionGrantValidator>(); builder.Services.AddTransient<BearerTokenUsageValidator>(); builder.Services.AddTransient<JwtRequestValidator>(); // todo: remove in 3.0 #pragma warning disable CS0618 // Type or member is obsolete builder.Services.AddTransient<BackChannelHttpClient>(); #pragma warning restore CS0618 // Type or member is obsolete builder.Services.AddTransient<ReturnUrlParser>(); builder.Services.AddTransient<IdentityServerTools>(); builder.Services.AddTransient<IReturnUrlParser, OidcReturnUrlParser>(); builder.Services.AddScoped<IUserSession, DefaultUserSession>(); builder.Services.AddTransient(typeof(MessageCookie<>)); builder.Services.AddCors(); builder.Services.AddTransientDecorator<ICorsPolicyProvider, CorsPolicyProvider>(); return builder; }
public static IIdentityServerBuilder AddDefaultEndpoints(this IIdentityServerBuilder builder) { builder.Services.AddTransient<IEndpointRouter, EndpointRouter>(); builder.AddEndpoint<AuthorizeCallbackEndpoint>(EndpointNames.Authorize, ProtocolRoutePaths.AuthorizeCallback.EnsureLeadingSlash()); builder.AddEndpoint<AuthorizeEndpoint>(EndpointNames.Authorize, ProtocolRoutePaths.Authorize.EnsureLeadingSlash()); builder.AddEndpoint<CheckSessionEndpoint>(EndpointNames.CheckSession, ProtocolRoutePaths.CheckSession.EnsureLeadingSlash()); builder.AddEndpoint<DeviceAuthorizationEndpoint>(EndpointNames.DeviceAuthorization, ProtocolRoutePaths.DeviceAuthorization.EnsureLeadingSlash()); builder.AddEndpoint<DiscoveryKeyEndpoint>(EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryWebKeys.EnsureLeadingSlash()); builder.AddEndpoint<DiscoveryEndpoint>(EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryConfiguration.EnsureLeadingSlash()); builder.AddEndpoint<EndSessionCallbackEndpoint>(EndpointNames.EndSession, ProtocolRoutePaths.EndSessionCallback.EnsureLeadingSlash()); builder.AddEndpoint<EndSessionEndpoint>(EndpointNames.EndSession, ProtocolRoutePaths.EndSession.EnsureLeadingSlash()); builder.AddEndpoint<IntrospectionEndpoint>(EndpointNames.Introspection, ProtocolRoutePaths.Introspection.EnsureLeadingSlash()); builder.AddEndpoint<TokenRevocationEndpoint>(EndpointNames.Revocation, ProtocolRoutePaths.Revocation.EnsureLeadingSlash()); builder.AddEndpoint<TokenEndpoint>(EndpointNames.Token, ProtocolRoutePaths.Token.EnsureLeadingSlash()); builder.AddEndpoint<UserInfoEndpoint>(EndpointNames.UserInfo, ProtocolRoutePaths.UserInfo.EnsureLeadingSlash()); return builder; }
public static IIdentityServerBuilder AddPluggableServices(this IIdentityServerBuilder builder) { builder.Services.TryAddTransient<IPersistedGrantService, DefaultPersistedGrantService>(); builder.Services.TryAddTransient<IKeyMaterialService, DefaultKeyMaterialService>(); builder.Services.TryAddTransient<ITokenService, DefaultTokenService>(); builder.Services.TryAddTransient<ITokenCreationService, DefaultTokenCreationService>(); builder.Services.TryAddTransient<IClaimsService, DefaultClaimsService>(); builder.Services.TryAddTransient<IRefreshTokenService, DefaultRefreshTokenService>(); builder.Services.TryAddTransient<IDeviceFlowCodeService, DefaultDeviceFlowCodeService>(); builder.Services.TryAddTransient<IConsentService, DefaultConsentService>(); builder.Services.TryAddTransient<ICorsPolicyService, DefaultCorsPolicyService>(); builder.Services.TryAddTransient<IProfileService, DefaultProfileService>(); builder.Services.TryAddTransient<IConsentMessageStore, ConsentMessageStore>(); builder.Services.TryAddTransient<IMessageStore<LogoutMessage>, ProtectedDataMessageStore<LogoutMessage>>(); builder.Services.TryAddTransient<IMessageStore<EndSession>, ProtectedDataMessageStore<EndSession>>(); builder.Services.TryAddTransient<IMessageStore<ErrorMessage>, ProtectedDataMessageStore<ErrorMessage>>(); builder.Services.TryAddTransient<IIdentityServerInteractionService, DefaultIdentityServerInteractionService>(); builder.Services.TryAddTransient<IDeviceFlowInteractionService, DefaultDeviceFlowInteractionService>(); builder.Services.TryAddTransient<IAuthorizationCodeStore, DefaultAuthorizationCodeStore>(); builder.Services.TryAddTransient<IRefreshTokenStore, DefaultRefreshTokenStore>(); builder.Services.TryAddTransient<IReferenceTokenStore, DefaultReferenceTokenStore>(); builder.Services.TryAddTransient<IUserConsentStore, DefaultUserConsentStore>(); builder.Services.TryAddTransient<IHandleGenerationService, DefaultHandleGenerationService>(); builder.Services.TryAddTransient<IPersistentGrantSerializer, PersistentGrantSerializer>(); builder.Services.TryAddTransient<IEventService, DefaultEventService>(); builder.Services.TryAddTransient<IEventSink, DefaultEventSink>(); builder.Services.TryAddTransient<IUserCodeService, DefaultUserCodeService>(); builder.Services.TryAddTransient<IUserCodeGenerator, NumericUserCodeGenerator>(); builder.Services.TryAddTransient<IBackChannelLogoutService, DefaultBackChannelLogoutService>(); builder.AddJwtRequestUriHttpClient(); builder.AddBackChannelLogoutHttpClient(); //builder.Services.AddHttpClient<BackChannelLogoutHttpClient>(); //builder.Services.AddHttpClient<JwtRequestUriHttpClient>(); builder.Services.AddTransient<IClientSecretValidator, ClientSecretValidator>(); builder.Services.AddTransient<IApiSecretValidator, ApiSecretValidator>(); builder.Services.TryAddTransient<IDeviceFlowThrottlingService, DistributedDeviceFlowThrottlingService>(); builder.Services.AddDistributedMemoryCache(); return builder; }
public static IIdentityServerBuilder AddValidators(this IIdentityServerBuilder builder) { // core builder.Services.TryAddTransient<IEndSessionRequestValidator, EndSessionRequestValidator>(); builder.Services.TryAddTransient<ITokenRevocationRequestValidator, TokenRevocationRequestValidator>(); builder.Services.TryAddTransient<IAuthorizeRequestValidator, AuthorizeRequestValidator>(); builder.Services.TryAddTransient<ITokenRequestValidator, TokenRequestValidator>(); builder.Services.TryAddTransient<IRedirectUriValidator, StrictRedirectUriValidator>(); builder.Services.TryAddTransient<ITokenValidator, TokenValidator>(); builder.Services.TryAddTransient<IIntrospectionRequestValidator, IntrospectionRequestValidator>(); builder.Services.TryAddTransient<IResourceOwnerPasswordValidator, NotSupportedResourceOwnerPasswordValidator>(); builder.Services.TryAddTransient<ICustomTokenRequestValidator, DefaultCustomTokenRequestValidator>(); builder.Services.TryAddTransient<IUserInfoRequestValidator, UserInfoRequestValidator>(); builder.Services.TryAddTransient<IClientConfigurationValidator, DefaultClientConfigurationValidator>(); builder.Services.TryAddTransient<IDeviceAuthorizationRequestValidator, DeviceAuthorizationRequestValidator>(); builder.Services.TryAddTransient<IDeviceCodeValidator, DeviceCodeValidator>(); // optional builder.Services.TryAddTransient<ICustomTokenValidator, DefaultCustomTokenValidator>(); builder.Services.TryAddTransient<ICustomAuthorizeRequestValidator, DefaultCustomAuthorizeRequestValidator>(); return builder; }
public static IIdentityServerBuilder AddResponseGenerators(this IIdentityServerBuilder builder) { builder.Services.TryAddTransient<ITokenResponseGenerator, TokenResponseGenerator>(); builder.Services.TryAddTransient<IUserInfoResponseGenerator, UserInfoResponseGenerator>(); builder.Services.TryAddTransient<IIntrospectionResponseGenerator, IntrospectionResponseGenerator>(); builder.Services.TryAddTransient<IAuthorizeInteractionResponseGenerator, AuthorizeInteractionResponseGenerator>(); builder.Services.TryAddTransient<IAuthorizeResponseGenerator, AuthorizeResponseGenerator>(); builder.Services.TryAddTransient<IDiscoveryResponseGenerator, DiscoveryResponseGenerator>(); builder.Services.TryAddTransient<ITokenRevocationResponseGenerator, TokenRevocationResponseGenerator>(); builder.Services.TryAddTransient<IDeviceAuthorizationResponseGenerator, DeviceAuthorizationResponseGenerator>(); return builder; }
/// <summary> /// Adds the default secret parsers. /// </summary> /// <param name="builder">The builder.</param> /// <returns></returns> public static IIdentityServerBuilder AddDefaultSecretParsers(this IIdentityServerBuilder builder) { builder.Services.AddTransient<ISecretParser, BasicAuthenticationSecretParser>(); builder.Services.AddTransient<ISecretParser, PostBodySecretParser>(); return builder; } /// <summary> /// Adds the default secret validators. /// </summary> /// <param name="builder">The builder.</param> /// <returns></returns> public static IIdentityServerBuilder AddDefaultSecretValidators(this IIdentityServerBuilder builder) { builder.Services.AddTransient<ISecretValidator, HashedSharedSecretValidator>(); return builder; }
/// <summary> /// The IdentityServerOptions class is the top level container for all configuration settings of IdentityServer. /// </summary> public class IdentityServerOptions { /// <summary> /// Gets or sets the unique name of this server instance, e.g. https://myissuer.com. /// If not set, the issuer name is inferred from the request /// </summary> /// <value> /// Unique name of this server instance, e.g. https://myissuer.com /// </value> public string IssuerUri { get; set; } /// <summary> /// Gets or sets the origin of this server instance, e.g. https://myorigin.com. /// If not set, the origin name is inferred from the request /// Note: Do not set a URL or include a path. /// </summary> /// <value> /// Origin of this server instance, e.g. https://myorigin.com /// </value> public string PublicOrigin { get; set; } /// <summary> /// Gets or sets the value for the JWT typ header for access tokens. /// </summary> /// <value> /// The JWT typ value. /// </value> public string AccessTokenJwtType { get; set; } = "at+jwt"; /// <summary> /// Emits an aud claim with the format issuer/resources. That's needed for some older access token validation plumbing. Defaults to false. /// </summary> public bool EmitLegacyResourceAudienceClaim { get; set; } = false; /// <summary> /// Gets or sets the endpoint configuration. /// </summary> /// <value> /// The endpoints configuration. /// </value> public EndpointsOptions Endpoints { get; set; } = new EndpointsOptions(); /// <summary> /// Gets or sets the discovery endpoint configuration. /// </summary> /// <value> /// The discovery endpoint configuration. /// </value> public DiscoveryOptions Discovery { get; set; } = new DiscoveryOptions(); /// <summary> /// Gets or sets the authentication options. /// </summary> /// <value> /// The authentication options. /// </value> public AuthenticationOptions Authentication { get; set; } = new AuthenticationOptions(); /// <summary> /// Gets or sets the events options. /// </summary> /// <value> /// The events options. /// </value> public EventsOptions Events { get; set; } = new EventsOptions(); /// <summary> /// Gets or sets the max input length restrictions. /// </summary> /// <value> /// The length restrictions. /// </value> public InputLengthRestrictions InputLengthRestrictions { get; set; } = new InputLengthRestrictions(); /// <summary> /// Gets or sets the options for the user interaction. /// </summary> /// <value> /// The user interaction options. /// </value> public UserInteractionOptions UserInteraction { get; set; } = new UserInteractionOptions(); /// <summary> /// Gets or sets the caching options. /// </summary> /// <value> /// The caching options. /// </value> public CachingOptions Caching { get; set; } = new CachingOptions(); /// <summary> /// Gets or sets the cors options. /// </summary> /// <value> /// The cors options. /// </value> public CorsOptions Cors { get; set; } = new CorsOptions(); /// <summary> /// Gets or sets the Content Security Policy options. /// </summary> public CspOptions Csp { get; set; } = new CspOptions(); /// <summary> /// Gets or sets the validation options. /// </summary> public ValidationOptions Validation { get; set; } = new ValidationOptions(); /// <summary> /// Gets or sets the device flow options. /// </summary> public DeviceFlowOptions DeviceFlow { get; set; } = new DeviceFlowOptions(); /// <summary> /// Gets or sets the mutual TLS options. /// </summary> public MutualTlsOptions MutualTls { get; set; } = new MutualTlsOptions(); }
public static IApplicationBuilder UseIdentityServer(this IApplicationBuilder app, IdentityServerMiddlewareOptions options = null) { app.Validate(); app.UseMiddleware<BaseUrlMiddleware>(); app.ConfigureCors(); // it seems ok if we have UseAuthentication more than once in the pipeline -- // this will just re-run the various callback handlers and the default authN // handler, which just re-assigns the user on the context. claims transformation // will run twice, since that's not cached (whereas the authN handler result is) // related: https://github.com/aspnet/Security/issues/1399 if (options == null) options = new IdentityServerMiddlewareOptions(); options.AuthenticationMiddleware(app); app.UseMiddleware<MutualTlsTokenEndpointMiddleware>(); app.UseMiddleware<IdentityServerMiddleware>(); return app; }
idsv的代碼量仍是比較大的,注入了大量的類。可是代碼風格比較規範,脈絡仍是很清晰的。