簡體   English   中英

將IdentityServer4軟件包從2.2.0更新到2.4.0之后,Identity Server 4無法正常登錄?ReturnUrl = / connect

[英]Identity server 4 not working signin?ReturnUrl=/connect after update IdentityServer4 package from 2.2.0 to 2.4.0

昨天我已經將Identity Server 4更新到版本2.4.0-該軟件包還包括一個必須執行並應用於Indentity數據庫的遷移(它向Client表等添加了一些列)。 更新版本並部署到我們的開發服務器后,在執行請求期間將重定向重定向到登錄?ReturnUrl = / connect身份服務器返回404。前端使用oidc-client與身份服務器進行通信。 我想指出的是,在升級到2.4.0之前,一切都按預期進行。 如果我手動導航到身份服務器的登錄頁面,則無法正確加載

更新此程序包后,我找不到問題所在,並且開始感覺到與此次遷移相關的問題,即我對新添加的列執行了其添加的默認值,並且可能其中一些不包含在oidc-client中

請幫我這讓我發瘋

oidc客戶端設置

  const settings: UserManagerSettings = {
  authority: 'https://login.' + appConfig.config.mainDomain + '/',
  client_id: environment.clientId,
  client_secret: environment.clientSecret,
  redirect_uri: window.location.origin + '/auth-callback',
  post_logout_redirect_uri: window.location.origin + '/',

  // these two will be done dynamically from the buttons clicked, but are
  // needed if you want to use the silent_renew
  response_type: 'id_token token',
  scope: 'openid profile address test',

  // this will toggle if profile endpoint is used
  loadUserInfo: true,
  // silent renew will get a new access_token via an iframe
  // just prior to the old access_token expiring (60 seconds prior)
  silent_redirect_uri: window.location.origin + '/assets/silent.html',
  automaticSilentRenew: true,
  // will revoke (reference) access tokens at logout time
  revokeAccessTokenOnSignout: true,
  // this will allow all the OIDC protocol claims to be visible in the window. normally a client app
  // wouldn't care about them or want them taking up space
  filterProtocolClaims: false
};

啟動文件

public void ConfigureServices(IServiceCollection services)
    {
        try
        {
            services.AddCors(options =>
            {
                // this defines a CORS policy called "default"
                options.AddPolicy("default", policy =>
                {
                    policy.AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            });
            if (windowsProvider != null && Convert.ToBoolean(windowsProvider[Constants.AuthenticationEnabled]))
            {
                services.Configure<IISOptions>(iis =>
                {
                    iis.AuthenticationDisplayName = windowsProvider[Constants.AuthenticationDisplayName];
                    iis.AutomaticAuthentication = false;
                });
            }

            var identityConnection = _mm.ConfManager.GetSection(Constants.DbConnections)[Constants.IdentityServerData];
            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
            services.AddMvc().AddMvcOptions(o => { o.Filters.Add(new GlobalExceptionFilter(_mm)); });
            services.AddIdentityServer(x => { x.PublicOrigin = _mm.ConfManager[Constants.PublicOrigin]; })
                .AddSigningCredential(Certificates.LoadCertificateFromStore(_mm.ConfManager[Constants.Certificate]))
                .AddBgoIdpUserStore()
                .AddRedirectUriValidator<AnyRedirectUriValidator>()
                .AddConfigurationStore(options => { options.ConfigureDbContext = builder => builder.UseSqlServer(identityConnection, sql => sql.MigrationsAssembly(migrationsAssembly)); })
                .AddOperationalStore(options => { options.ConfigureDbContext = builder => builder.UseSqlServer(identityConnection, sql => sql.MigrationsAssembly(migrationsAssembly)); });

            services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; })
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
                {
                    options.LoginPath = new PathString(Constants.SignIn);
                    options.LogoutPath = new PathString(Constants.SignOut);
                    options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
                });



            services.AddLocalApiAuthentication();
        }
        catch (Exception ex)
        {
            _mm.LogErrMessage(ex.Message);
            _mm.LogTraceException(ex, ex.Message);
        }
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IDPUserContext idpUserContext, ConfigurationDbContext configurationDbContext, PersistedGrantDbContext persistedGrantDbContext)
    {
        try
        {


            // global policy - assign here or on each controller
            app.UseCors("default");
            app.UseExceptionHandler(Constants.ExceptionHandler);

            app.Use(async (context, next) =>
            {
                if (context.Request.QueryString.HasValue)
                {
                    if (!context.Request.Headers.ContainsKey("Authorization"))
                    {
                        var queryString = HttpUtility.ParseQueryString(context.Request.QueryString.Value);
                        string token = queryString.Get("access_token");

                        if (!string.IsNullOrWhiteSpace(token))
                        {
                            context.Request.Headers.Add("Authorization", new[] { string.Format("Bearer {0}", token) });
                        }
                    }
                }

                await next.Invoke();
            });


            app.UseIdentityServer();
            app.UseAuthentication();
            app.UseStaticFiles();
            app.UseMiddleware(typeof(ErrorHandlingMiddleware));
            app.UseMvcWithDefaultRoute();

        }

這是GetClients()

public static IEnumerable < Client > GetClients() {
return new List < Client > () {

    new Client {
        ClientName = "JS dev client",
            ClientId = "JSDevClient",
            AllowedCorsOrigins = {
                "http://mfm.localhost",
                "https://mfm.localhost",
                "https://test.test.app",
                "http://test.test.app",
                "https://localhost:4200",
                "http://localhost:4200",
                "https://test.app",
                "https://*.test.app"
            },
            AccessTokenType = AccessTokenType.Reference,

            //TODO: Not sure if we need the second screen ,check with the business
            RequireConsent = false, // setting usage or not for consent screen

            AccessTokenLifetime = 1200,
            AuthorizationCodeLifetime = 1200,
            IdentityTokenLifetime = 1200,
            UpdateAccessTokenClaimsOnRefresh = true,
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true,

            ClientSecrets = {
                new Secret("jsdevclient;dorgfgitvzmoygksqjpm,".Sha256())
            },
            AllowedGrantTypes = GrantTypes.Implicit,
            RedirectUris = new List < string > {
                "http://mfm.localhost/callback.html",
                "http://mfm.localhost/auth-callback",
                "https://mfm.localhost/auth-callback",
                "https://test.test.app/assets/silent.html",
                "http://test.test.app/assets/silent.html",
                "https://test.test.app/auth-callback",
                "http://test.test.app/auth-callback",
                "https://*.test.app/assets/silent.html",
                "https://*.test.app/auth-callback",
                "http://localhost:4200/auth-callback",
                "https://localhost:4200/auth-callback",
                "http://localhost:4200/assets/silent.html",
                "https://localhost:4200/assets/silent.html"
            },
            AllowedScopes = {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Address,
                "testapi",
            },
            PostLogoutRedirectUris = {
                "http://mfm.localhost/index.html",
                "http://mfm.localhost/",
                "https://mfm.localhost/",
                "https://dev-test.metaforms.app",
                "http://dev-test.metaforms.app",
                "http://localhost:4200",
                "https://localhost:4200",
                "https://test.app",
                "https://test.app",
                "https://*.test.app",
                "https://test.metaforms.app",
                "http://test.metaforms.app"
            },
            AlwaysIncludeUserClaimsInIdToken = true,
    },
};

}

應用遷移

protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<DateTime>(
            name: "Created",
            table: "IdentityResources",
            nullable: false,
            defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

        migrationBuilder.AddColumn<bool>(
            name: "NonEditable",
            table: "IdentityResources",
            nullable: false,
            defaultValue: false);

        migrationBuilder.AddColumn<DateTime>(
            name: "Updated",
            table: "IdentityResources",
            nullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Value",
            table: "ClientSecrets",
            maxLength: 4000,
            nullable: false,
            oldClrType: typeof(string),
            oldMaxLength: 2000);

        migrationBuilder.AlterColumn<string>(
            name: "Type",
            table: "ClientSecrets",
            maxLength: 250,
            nullable: false,
            oldClrType: typeof(string),
            oldMaxLength: 250,
            oldNullable: true);

        migrationBuilder.AddColumn<DateTime>(
            name: "Created",
            table: "ClientSecrets",
            nullable: false,
            defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

        migrationBuilder.AddColumn<DateTime>(
            name: "Created",
            table: "Clients",
            nullable: false,
            defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

        migrationBuilder.AddColumn<int>(
            name: "DeviceCodeLifetime",
            table: "Clients",
            nullable: false,
            defaultValue: 0);

        migrationBuilder.AddColumn<DateTime>(
            name: "LastAccessed",
            table: "Clients",
            nullable: true);

        migrationBuilder.AddColumn<bool>(
            name: "NonEditable",
            table: "Clients",
            nullable: false,
            defaultValue: false);

        migrationBuilder.AddColumn<DateTime>(
            name: "Updated",
            table: "Clients",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "UserCodeType",
            table: "Clients",
            maxLength: 100,
            nullable: true);

        migrationBuilder.AddColumn<int>(
            name: "UserSsoLifetime",
            table: "Clients",
            nullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Value",
            table: "ApiSecrets",
            maxLength: 4000,
            nullable: false,
            oldClrType: typeof(string),
            oldMaxLength: 2000,
            oldNullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Type",
            table: "ApiSecrets",
            maxLength: 250,
            nullable: false,
            oldClrType: typeof(string),
            oldMaxLength: 250,
            oldNullable: true);

        migrationBuilder.AddColumn<DateTime>(
            name: "Created",
            table: "ApiSecrets",
            nullable: false,
            defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

        migrationBuilder.AddColumn<DateTime>(
            name: "Created",
            table: "ApiResources",
            nullable: false,
            defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));

        migrationBuilder.AddColumn<DateTime>(
            name: "LastAccessed",
            table: "ApiResources",
            nullable: true);

        migrationBuilder.AddColumn<bool>(
            name: "NonEditable",
            table: "ApiResources",
            nullable: false,
            defaultValue: false);

        migrationBuilder.AddColumn<DateTime>(
            name: "Updated",
            table: "ApiResources",
            nullable: true);

        migrationBuilder.CreateTable(
            name: "ApiProperties",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                Key = table.Column<string>(maxLength: 250, nullable: false),
                Value = table.Column<string>(maxLength: 2000, nullable: false),
                ApiResourceId = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_ApiProperties", x => x.Id);
                table.ForeignKey(
                    name: "FK_ApiProperties_ApiResources_ApiResourceId",
                    column: x => x.ApiResourceId,
                    principalTable: "ApiResources",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateTable(
            name: "IdentityProperties",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                Key = table.Column<string>(maxLength: 250, nullable: false),
                Value = table.Column<string>(maxLength: 2000, nullable: false),
                IdentityResourceId = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_IdentityProperties", x => x.Id);
                table.ForeignKey(
                    name: "FK_IdentityProperties_IdentityResources_IdentityResourceId",
                    column: x => x.IdentityResourceId,
                    principalTable: "IdentityResources",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateIndex(
            name: "IX_ApiProperties_ApiResourceId",
            table: "ApiProperties",
            column: "ApiResourceId");

        migrationBuilder.CreateIndex(
            name: "IX_IdentityProperties_IdentityResourceId",
            table: "IdentityProperties",
            column: "IdentityResourceId");
    }

這是從日志

2019-08-29 10:43:47.300 +03:00 [WRN] App is started
2019-08-29 10:43:47.577 +03:00 [DBG] Login Url: /signin
2019-08-29 10:43:47.579 +03:00 [DBG] Login Return Url Parameter: ReturnUrl
2019-08-29 10:43:47.580 +03:00 [DBG] Logout Url: /signout
2019-08-29 10:43:47.580 +03:00 [DBG] ConsentUrl Url: /consent
2019-08-29 10:43:47.580 +03:00 [DBG] Consent Return Url Parameter: returnUrl
2019-08-29 10:43:47.580 +03:00 [DBG] Error Url: /home/error
2019-08-29 10:43:47.580 +03:00 [DBG] Error Id Parameter: errorId
2019-08-29 10:44:26.740 +03:00 [DBG] CORS request made for path: /.well-known/openid-configuration from origin: https://test.test.app
2019-08-29 10:44:26.767 +03:00 [DBG] Origin https://test.test.app is allowed: true
2019-08-29 10:44:26.773 +03:00 [DBG] CorsPolicyService allowed origin: https://test.test.app
2019-08-29 10:44:26.774 +03:00 [DBG] Request path /.well-known/openid-configuration matched to endpoint type Discovery
2019-08-29 10:44:26.790 +03:00 [DBG] Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint
2019-08-29 10:44:26.790 +03:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
2019-08-29 10:44:26.808 +03:00 [DBG] Start discovery request
2019-08-29 10:44:27.756 +03:00 [DBG] Found openid, profile, address, roles, country, subscriptionlevel, metaformsmanagerapi, metaformsbrowserapi, metaformsnavigatorapi, emailprocessorapi, servicebusapi, filestoreapi, jstest, metaformsfrontend, IdentityServerApi as all scopes in database
2019-08-29 10:44:27.856 +03:00 [DBG] Request path /connect/authorize matched to endpoint type Authorize
2019-08-29 10:44:27.861 +03:00 [DBG] Endpoint enabled: Authorize, successfully created handler: IdentityServer4.Endpoints.AuthorizeEndpoint
2019-08-29 10:44:27.861 +03:00 [INF] Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
2019-08-29 10:44:27.865 +03:00 [DBG] Start authorize request
2019-08-29 10:44:27.883 +03:00 [DBG] No user present in authorize request
2019-08-29 10:44:27.890 +03:00 [DBG] Start authorize request protocol validation
2019-08-29 10:44:28.224 +03:00 [DBG] JSDevClient found in database: true
2019-08-29 10:44:28.232 +03:00 [DBG] client configuration validation for client JSDevClient succeeded.
2019-08-29 10:44:28.300 +03:00 [DBG] Found openid, profile, address identity scopes in database
2019-08-29 10:44:28.353 +03:00 [DBG] Found test API scopes in database
2019-08-29 10:44:28.366 +03:00 [DBG] Found openid, profile, address identity scopes in database
2019-08-29 10:44:28.370 +03:00 [DBG] Found metaformsmanagerapi API scopes in database
2019-08-29 10:44:28.380 +03:00 [DBG] Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator
2019-08-29 10:44:28.432 +03:00 [INF] ValidatedAuthorizeRequest
{
"ClientId": "JSDevClient",
"ClientName": "JS dev client",
"RedirectUri": "https://test.test.app/auth-callback",
"AllowedRedirectUris": ["https://*.test.app/assets/silent.html", "http://mfm.localhost/callback.html", "http://mfm.localhost/auth-callback", "https://mfm.localhost/auth-callback", "https://test.test.app/assets/silent.html", "http://test.test.app/assets/silent.html", "https://test.test.app/auth-callback", "http://test.test.app/auth-callback", "https://*.test.app/auth-callback", "http://localhost:4200/auth-callback", "https://localhost:4200/auth-callback", "http://localhost:4200/assets/silent.html", "https://localhost:4200/assets/silent.html"],
"SubjectId": "anonymous",
"ResponseType": "id_token token",
"ResponseMode": "fragment",
"GrantType": "implicit",
"RequestedScopes": "openid profile address testapi",
"State": "dffeb4fca72e43afaecb5fb5daff2348",
"UiLocales": null,
"Nonce": "8dad56338d7f40b595a9f2d91aba18d0",
"AuthenticationContextReferenceClasses": null,
"DisplayMode": null,
"PromptMode": null,
"MaxAge": null,
"LoginHint": null,
"SessionId": null,
"Raw": {
    "client_id": "JSDevClient",
    "redirect_uri": "https://test.test.app/auth-callback",
    "response_type": "id_token token",
    "scope": "openid profile address testapi",
    "state": "dffeb4fca72e43afaecb5fb5daff2348",
    "nonce": "8dad56338d7f40b595a9f2d91aba18d0"
},
"$type": "AuthorizeRequestValidationLog"
}
 2019-08-29 10:44:28.497 +03:00 [INF] Showing login: User is not authenticated
 2019-08-29 10:44:28.499+03:00 [INF] Cookies was not authenticated. Failure message: Unprotect ticket failed
 2019-08-29 10:44:28.499 +03:00 [INF] Cookies was not authenticated. Failure message: Unprotect ticket failed
 2019-08-29 10:44:28.499 +03:00 [INF] Cookies was not authenticated. Failure message: Unprotect ticket failed

我找到了導致問題的原因,但我不知道為什么

 services.AddAuthentication(options => { options.DefaultScheme = 
    CookieAuthenticationDefaults.AuthenticationScheme; })
   .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    {
     //options.LoginPath = new PathString(Constants.SignIn);
     //options.LogoutPath = new PathString(Constants.SignOut);
     options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
    });

在我注釋它們后,這兩行分別注釋LoginPath(/ signin)和LogoutPath(/ signout),一切都按預期進行。 請問能否提供更多信息,為什么我會遇到這種行為

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM