具有Google身份验证和邮递员的IdentityServer4

红翼飞机

我将IdentityServer4IdentityServer4.UIauthorization_code一起使用Google authentication

这是我的Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // ...
    const string connectionString = @"Data Source=.\SQLEXPRESS;database=Is4.LearnIs4;trusted_connection=yes;";
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    services
        .AddIdentityServer()
        .AddDeveloperSigningCredential()
        //.AddProfileService<IdentityServerProfileService>()
        //.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
        // this adds the config data from DB (clients, resources)
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder =>
            {
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
            };
        })
        // this adds the operational data from DB (codes, tokens, consents)
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
            // this enables automatic token cleanup. this is optional.
            options.EnableTokenCleanup = true;
        });

    // Add jwt validation.
    services
        .AddAuthentication()
        .AddGoogle("Google", options =>
        {
            options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

            options.ClientId = "<my-client-id>";
            options.ClientSecret = "<my-secret>";

            options.AccessType = "offline";
        })
        .AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
        {
            options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
            options.SignOutScheme = IdentityServerConstants.SignoutScheme;

            options.Authority = "http://localhost:57547";
            options.ClientId = "implicit";
            options.ResponseType = "id_token";
            options.SaveTokens = true;
            options.CallbackPath = new PathString("/signin-idsrv");
            options.SignedOutCallbackPath = new PathString("/signout-callback-idsrv");
            options.RemoteSignOutPath = new PathString("/signout-idsrv");
            options.RequireHttpsMetadata = false;

            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
                RoleClaimType = "role"
            };
        });
    // ...
}

这些是我的客户端配置:


/// <summary>
/// Seed database.
/// </summary>
/// <param name="app"></param>
public static void Seed(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

        var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
        context.Database.Migrate();
        if (!context.Clients.Any())
        {
            foreach (var client in LoadClients())
                context.Clients.Add(client.ToEntity());
            context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            foreach (var resource in LoadIdentityResources())
                context.IdentityResources.Add(resource.ToEntity());
            context.SaveChanges();
        }

        if (!context.ApiResources.Any())
        {
            foreach (var resource in LoadApiResources())
                context.ApiResources.Add(resource.ToEntity());
            context.SaveChanges();
        }
    }
}

/// <summary>
/// Load pre-defined identity resource.
/// </summary>
/// <returns></returns>
private static IEnumerable<IdentityResource> LoadIdentityResources()
{
    var identityResources = new List<IdentityResource>();
    identityResources.Add(new IdentityResources.OpenId());
    identityResources.Add(new IdentityResources.Profile());

    return identityResources;
}

/// <summary>
/// Load pre-defined api resources.
/// </summary>
/// <returns></returns>
private static IEnumerable<ApiResource> LoadApiResources()
{
    var apiResources = new List<ApiResource>();

    var api1Resource = new ApiResource("api1", "My API");
    api1Resource.ApiSecrets = new List<Secret>();
    api1Resource.ApiSecrets.Add(new Secret("secret".Sha256()));
    apiResources.Add(api1Resource);

    return apiResources;
}

/// <summary>
/// Load pre-defined clients.
/// </summary>
/// <returns></returns>
private static IEnumerable<Client> LoadClients()
{
    var clients = new List<Client>();

    var clientCredentialClient = new Client();
    clientCredentialClient.ClientId = "client";
    clientCredentialClient.AllowedGrantTypes = GrantTypes.ClientCredentials;
    clientCredentialClient.ClientSecrets = new List<Secret>();
    clientCredentialClient.ClientSecrets.Add(new Secret("secret".Sha256()));
    clientCredentialClient.AllowedScopes = new List<string>();
    clientCredentialClient.AllowedScopes.Add("api1");
    clients.Add(clientCredentialClient);

    var resourceOwnerPasswordClient = new Client();
    resourceOwnerPasswordClient.ClientId = "ro.client";
    resourceOwnerPasswordClient.AllowedGrantTypes = new List<string>();
    resourceOwnerPasswordClient.AllowedGrantTypes.Add(GrantType.ResourceOwnerPassword);
    resourceOwnerPasswordClient.AllowedGrantTypes.Add("refresh_token");
    resourceOwnerPasswordClient.ClientSecrets = new List<Secret>();
    resourceOwnerPasswordClient.ClientSecrets.Add(new Secret("secret".Sha256()));
    resourceOwnerPasswordClient.AllowedScopes = new List<string>();
    resourceOwnerPasswordClient.AllowedScopes.Add("api1");
    resourceOwnerPasswordClient.AllowOfflineAccess = true;
    resourceOwnerPasswordClient.RefreshTokenExpiration = TokenExpiration.Sliding;
    resourceOwnerPasswordClient.RefreshTokenUsage = TokenUsage.ReUse;
    resourceOwnerPasswordClient.SlidingRefreshTokenLifetime = 3600;
    clients.Add(resourceOwnerPasswordClient);

    var authorizationCodeClient = new Client();
    authorizationCodeClient.ClientId = "mvc";
    authorizationCodeClient.ClientName = "MVC Client";
    authorizationCodeClient.AllowedGrantTypes = new List<string>();
    authorizationCodeClient.AllowedGrantTypes.Add(GrantType.AuthorizationCode);
    authorizationCodeClient.ClientSecrets = new List<Secret>();
    authorizationCodeClient.ClientSecrets.Add(new Secret("secret".Sha256()));
    authorizationCodeClient.RedirectUris = new List<string>();
    authorizationCodeClient.RedirectUris.Add("http://localhost:4300");
    authorizationCodeClient.PostLogoutRedirectUris = new List<string>();
    authorizationCodeClient.PostLogoutRedirectUris.Add("http://localhost:5002/signout-callback-oidc");
    authorizationCodeClient.RequirePkce = false;
    authorizationCodeClient.AllowedScopes = new List<string>();
    authorizationCodeClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.OpenId);
    authorizationCodeClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.Profile);
    authorizationCodeClient.AllowedScopes.Add("api1");
    authorizationCodeClient.AllowOfflineAccess = true;
    authorizationCodeClient.RequireConsent = false;
    clients.Add(authorizationCodeClient);

    var codeClient = new Client();
    codeClient.ClientId = "js";
    codeClient.ClientName = "JavaScript Client";
    codeClient.AllowedGrantTypes = GrantTypes.Code;
    codeClient.RequirePkce = true;
    codeClient.RequireClientSecret = false;
    codeClient.RedirectUris = new List<string>();
    codeClient.RedirectUris.Add("http://localhost:5003/callback.html");
    codeClient.PostLogoutRedirectUris = new List<string>();
    codeClient.PostLogoutRedirectUris.Add("http://localhost:5003/index.html");
    codeClient.AllowedCorsOrigins = new List<string>();
    codeClient.AllowedCorsOrigins.Add("http://localhost:5003");
    codeClient.AllowedScopes = new List<string>();
    codeClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.OpenId);
    codeClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.Profile);
    codeClient.AllowedScopes.Add("api1");
    clients.Add(codeClient);

    return clients;
}

我向IdentityServer4发出了请求,如下图所示:

在此处输入图片说明

显示一个弹出窗口:

在此处输入图片说明

如果使用username登录password,我可以得到access_token但是当我点击Google按钮时Account/Login,我什么也收不到access token

这就是我得到的Visual Studio ouput

IdentityServer4.EntityFramework.Stores.PersistedGrantStore:Debug: P+z5g2/MhMzrbCEGMZOgx06VKeB38F1yx/y3C08vZlo= found in database: False
IdentityServer4.Stores.DefaultAuthorizationCodeStore:Debug: authorization_code grant with value: 4/KQGa0Oj2BztGi86v5SbFD0oVvnXIV8dZWFAQS16O-tyFVOcZXWvRQbByFb18Hhco5SgmkAQtPvk1ZD8lY8eLN9Q not found in store.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 338.1411ms 500 text/html; charset=utf-8
IdentityServer4.Validation.TokenRequestValidator:Error: Invalid authorization code{ code = 4/KQGa0Oj2BztGi86v5SbFD0oVvnXIV8dZWFAQS16O-tyFVOcZXWvRQbByFb18Hhco5SgmkAQtPvk1ZD8lY8eLN9Q }, details: {
  "ClientId": "mvc",
  "ClientName": "MVC Client",
  "GrantType": "authorization_code",
  "AuthorizationCode": "4/KQGa0Oj2BztGi86v5SbFD0oVvnXIV8dZWFAQS16O-tyFVOcZXWvRQbByFb18Hhco5SgmkAQtPvk1ZD8lY8eLN9Q",
  "Raw": {
    "grant_type": "authorization_code",
    "code": "4/KQGa0Oj2BztGi86v5SbFD0oVvnXIV8dZWFAQS16O-tyFVOcZXWvRQbByFb18Hhco5SgmkAQtPvk1ZD8lY8eLN9Q",
    "redirect_uri": "http://localhost:57547/signin-idsrv",
    "client_id": "mvc",
    "client_secret": "***REDACTED***"
  }
}

我做错什么了吗?

谢谢。

红翼飞机

似乎被authorization_code授予不适合这种情况。当我更改authorization_codehybrid授予时,它可以工作。

实际上,我更改了:

authorizationCodeClient.AllowedGrantTypes = new List<string>();
authorizationCodeClient.AllowedGrantTypes.Add(GrantType.AuthorizationCode);

authorizationCodeClient.AllowedGrantTypes = GrantTypes.Hybrid;

使用https://oidcdebugger.com/生成查询字符串:

http:// localhost:57547 / connect / authorize?client_id = mvc&redirect_uri = http%3A%2F%2Flocalhost%3A4300&scope = api1%20offline_access%20openid&response_type = code%20token%20id_token&response_mode = fragment&nonce = 556bs2pazg2

神奇的是,我可以使用帐户和密码以及Google帐户登录系统

希望这可以像我一样帮助某人卡在IdentityServer4中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

具有Windows身份验证和自定义声明的IdentityServer4

Laravel Passport - 使用邮递员进行身份验证

邮递员自定义身份验证

Odoo 14 的邮递员身份验证

IdentityServer4 和 Windows 身份验证

具有Windows / AD身份验证的IdentityServer4无法正常工作?

具有IdentityServer4,Asp.Net Core身份和不带实体框架的自定义提供程序的Blazor WebAssembly身份验证

使用邮递员和tv4针对具有多个元素的json数组验证jsonschema

邮递员:如何为使用Google OAuth2的Web应用程序进行身份验证?

Twitter API邮递员:代码32:无法对您进行身份验证

带邮递员的FCM-请求缺少身份验证密钥(FCM令牌)

护照身份验证可通过邮递员进行,但不能通过fetch()进行

无法获得IdentityServer4注销以进行外部(Google)身份验证

IdentityServer4直接链接到Facebook身份验证

通过ASP Core MVC,Web API和IdentityServer4的身份验证?

使用 MVC 客户端 4.7.1 和 IdentityServer4 进行身份验证

一个项目中的 IdentityServer4 和 Web Api 无法通过身份验证

带有UI的LDAP / AD身份验证的IdentityServer4

带有aspnet核心MVC OIDC身份验证的IdentityServer4 - api范围限制?

是否可以仅通过REST调用使identityserver4中的身份验证有效?

在Linux和Azure存储库上运行的Docker映像中的IdentityServer4和身份验证问题

春季启动:基本身份验证返回401但可以在邮递员中工作

尝试使用“邮递员”并在设置基本访问身份验证标头时遇到问题

邮递员对Amazon Alexa Smart Home Skill LWA的请求中的客户端身份验证失败

Firebase和邮递员| 为Google身份OAuth 2.0令牌生成JWT

使用IdentityServer4从单个客户端接受Bearer身份验证和OpenIdConnect时的奇怪行为

使用TV4的邮递员架构验证

如何使用AVJ和邮递员验证JSON模式

具有意外特征线的邮递员变量