IdentityServer / IdentityServer4.Templates

dotnet new templates for IdentityServer4
Apache License 2.0
695 stars 229 forks source link

Fresh Install of is4aspid template doesn't work with Google or Identity Auth #78

Closed breynolds closed 2 years ago

breynolds commented 4 years ago

We built up an identity server after successfully going through the first few quickstarts. We have Client Credentials, native app (dotnet core console app), and javascript apps all working with test users and with Google. Also did the quickstart to add in database support for config and operational data. All good.

Upon trying to complete the ASP.Net Core Identity quickstart, the regular users work, but we cannot get google authentication working. Clicking the google login bug briefly flickers to another page, but then we are redirected back to the login page.

I added steps to reproduce the problem and the log from identity server.

I starred a few lines in the log where you can see that the google login succeeded, but then somehow later the user was treated as not having logged in which I guess is why the user is redirected back to the login page. What is missing in between that causes the correctly logged in user to be lost?

Identity logins also fail, so it's not just google.

Don't know if it's relevant, buy I'm working on a MacBook Pro using the latest OS 10.15.5

Issue / Steps to reproduce the problem

dotnet new -u IdentityServer4.Templates dotnet new -i IdentityServer4.Templates dotnet new is4aspid -n IdentityServerAspNetIdentity

in launchSettings.json, change applicationUrl to http://localhost:5000 so it matches the test apps

in Config.cs, add in Email as an identity resource as well as the ApiResource that is required for our API:

public static IEnumerable<IdentityResource> Ids =>
            new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                new IdentityResources.Email()
            };

        public static IEnumerable<ApiResource> Apis =>
            new ApiResource[]
            {
                new ApiResource("api1", "My API #1"),
                new ApiResource("hnidentity", "HereNow API")
            };

in Config.cs, add in clients that work with non aspid identityserver:

                new Client
                {
                    ClientId = "js",
                    ClientName = "JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Code,
                    RequirePkce = true,
                    RequireClientSecret = false,
                    RedirectUris =           { "http://localhost:5003/callback.html" },
                    PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
                    AllowedCorsOrigins =     { "http://localhost:5003" },
                    AllowedScopes = { "openid", "profile", "api1", "email", "hnidentity" }

                },
                new Client
                {
                    ClientId = "native.code",
                    ClientName = "Native Client (Code with PKCE)",
                    AllowedGrantTypes = GrantTypes.Code,
                    RequirePkce = true,
                    RequireClientSecret = false,
                    RedirectUris = { "http://127.0.0.1:45678" },
                    PostLogoutRedirectUris = { "http://127.0.0.1:45678" },
                    AllowedScopes = { "openid", "profile", "api1", "email", "hnidentity" },
                    AllowOfflineAccess = true,
                    RefreshTokenUsage = TokenUsage.ReUse
                }

In startup.cs, update Google configuration for ClientId and ClientSecret that are working in our other non-aspid identity server (leaving the actual values out of the bug report, but they are correct in the file):

                    // options.ClientId = "copy client ID from Google here";
                    // options.ClientSecret = "copy client secret from Google here";

dotnet run

=> The effect is that upon clicking on the Google login button, a page flickers in and then leaves, and we are redirected to the login page rather than being given the consent page in google. The normal username/password logins for bob / Pass123$ also fail.

Relevant parts of the log file

[07:28:19 Information] 
Starting host...

[07:28:20 Information] IdentityServer4.Startup
Starting IdentityServer4 version 3.1.3.0

[07:28:20 Information] IdentityServer4.Startup
You are using the in-memory version of the persisted grant store. This will store consent decisions, authorization codes, refresh and reference tokens in memory only. If you are using any of those features in production, you want to switch to a different store implementation.

[07:28:20 Information] IdentityServer4.Startup
Using the default authentication scheme Identity.Application for IdentityServer

[07:28:20 Debug] IdentityServer4.Startup
Using Identity.Application as default ASP.NET Core scheme for authentication

[07:28:20 Debug] IdentityServer4.Startup
Using Identity.External as default ASP.NET Core scheme for sign-in

[07:28:20 Debug] IdentityServer4.Startup
Using Identity.External as default ASP.NET Core scheme for sign-out

[07:28:20 Debug] IdentityServer4.Startup
Using Identity.Application as default ASP.NET Core scheme for challenge

[07:28:20 Debug] IdentityServer4.Startup
Using Identity.Application as default ASP.NET Core scheme for forbid

[07:28:29 Debug] IdentityServer4.Startup
Login Url: /Account/Login

[07:28:29 Debug] IdentityServer4.Startup
Login Return Url Parameter: ReturnUrl

[07:28:29 Debug] IdentityServer4.Startup
Logout Url: /Account/Logout

[07:28:29 Debug] IdentityServer4.Startup
ConsentUrl Url: /consent

[07:28:29 Debug] IdentityServer4.Startup
Consent Return Url Parameter: returnUrl

[07:28:29 Debug] IdentityServer4.Startup
Error Url: /home/error

[07:28:29 Debug] IdentityServer4.Startup
Error Id Parameter: errorId

[07:28:29 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration matched to endpoint type Discovery

[07:28:29 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryEndpoint

[07:28:29 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration

[07:28:29 Debug] IdentityServer4.Endpoints.DiscoveryEndpoint
Start discovery request

[07:28:30 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /.well-known/openid-configuration/jwks matched to endpoint type Discovery

[07:28:30 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Discovery, successfully created handler: IdentityServer4.Endpoints.DiscoveryKeyEndpoint

[07:28:30 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks

[07:28:30 Debug] IdentityServer4.Endpoints.DiscoveryKeyEndpoint
Start key discovery request

[07:28:30 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /connect/authorize matched to endpoint type Authorize

[07:28:30 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Authorize, successfully created handler: IdentityServer4.Endpoints.AuthorizeEndpoint

[07:28:30 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize

[07:28:30 Debug] IdentityServer4.Endpoints.AuthorizeEndpoint
Start authorize request

[07:28:30 Debug] IdentityServer4.Endpoints.AuthorizeEndpoint
No user present in authorize request

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Start authorize request protocol validation

[07:28:30 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Checking for PKCE parameters

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator

[07:28:30 Debug] IdentityServer4.Endpoints.AuthorizeEndpoint
ValidatedAuthorizeRequest
{"ClientId": "native.code", "ClientName": "Native Client (Code with PKCE)", "RedirectUri": "http://127.0.0.1:45678", "AllowedRedirectUris": ["http://127.0.0.1:45678"], "SubjectId": "anonymous", "ResponseType": "code", "ResponseMode": "query", "GrantType": "authorization_code", "RequestedScopes": "openid profile email api1", "State": "QI2EYPTPXC5Em7C7Dj9l2A", "UiLocales": null, "Nonce": "Zj81W6UhQv9w_lAmK-anDA", "AuthenticationContextReferenceClasses": null, "DisplayMode": null, "PromptMode": null, "MaxAge": null, "LoginHint": null, "SessionId": "", "Raw": {"response_type": "code", "nonce": "Zj81W6UhQv9w_lAmK-anDA", "state": "QI2EYPTPXC5Em7C7Dj9l2A", "code_challenge": "LdnZafkNy5oI7M42U6mZv2NbKLECh8OXN0NvVVtOBrk", "code_challenge_method": "S256", "client_id": "native.code", "scope": "openid profile email api1", "redirect_uri": "http://127.0.0.1:45678"}, "$type": "AuthorizeRequestValidationLog"}

[07:28:30 Information] IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator
Showing login: User is not authenticated

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Start authorize request protocol validation

[07:28:30 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Checking for PKCE parameters

[07:28:30 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator

[07:28:30 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:34 Information] Microsoft.AspNetCore.Authentication.Google.GoogleHandler
AuthenticationScheme: Google was challenged.

[07:28:35 Information] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
**AuthenticationScheme: Identity.External signed in.**

[07:28:35 Debug] IdentityServer4.Quickstart.UI.ExternalController
External claims: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier:xxxxxxxxxxxxxxxxxxxxxxxxxxx", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: Brian Reynolds", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: Brian", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname: Reynolds", "urn:google:profile: https://plus.google.com/xxxxxxxxxxxxxxxxxxxxxxx", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: brian.reynolds@xxxxxxxxxxx.com"]

[07:28:36 Debug] IdentityServer4.Hosting.IdentityServerAuthenticationService
Augmenting SignInContext

[07:28:36 Debug] IdentityServer4.Hosting.IdentityServerAuthenticationService
Adding amr claim with value: external

[07:28:36 Debug] IdentityServer4.Hosting.IdentityServerAuthenticationService
Adding auth_time claim with value: 1592738916

[07:28:36 Information] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.Application signed in.

[07:28:36 Information] Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler
AuthenticationScheme: Identity.External signed out.

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Start authorize request protocol validation

[07:28:36 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Checking for PKCE parameters

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator

[07:28:36 Information] IdentityServer4.Events.DefaultEventService
{"Username": null, "Provider": "Google", "ProviderUserId": "xxxxxxxxxxxxxxxxxxxxxxxxx", "SubjectId": "0591eedf-63a9-4202-885b-c33141e94afe", "DisplayName": "Brian Reynolds", "Endpoint": "UI", "ClientId": "native.code", "Category": "Authentication", "Name": "User Login Success", "EventType": "Success", "Id": 1000, "Message": null, "ActivityId": "0HM0LQOSHT1MU:00000005", "TimeStamp": "2020-06-21T11:28:36.0000000Z", "ProcessId": 78712, "LocalIpAddress": "::1:5000", "RemoteIpAddress": "::1", "$type": "UserLoginSuccessEvent"}

[07:28:36 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:36 Debug] IdentityServer4.Hosting.EndpointRouter
Request path /connect/authorize/callback matched to endpoint type Authorize

[07:28:36 Debug] IdentityServer4.Hosting.EndpointRouter
Endpoint enabled: Authorize, successfully created handler: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint

[07:28:36 Information] IdentityServer4.Hosting.IdentityServerMiddleware
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint for /connect/authorize/callback

[07:28:36 Debug] IdentityServer4.Endpoints.AuthorizeCallbackEndpoint
Start authorize callback request

[07:28:36 Debug] IdentityServer4.Endpoints.AuthorizeCallbackEndpoint
**No user present in authorize request**

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Start authorize request protocol validation

[07:28:36 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Checking for PKCE parameters

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator

[07:28:36 Debug] IdentityServer4.Endpoints.AuthorizeCallbackEndpoint
ValidatedAuthorizeRequest
{"ClientId": "native.code", "ClientName": "Native Client (Code with PKCE)", "RedirectUri": "http://127.0.0.1:45678", "AllowedRedirectUris": ["http://127.0.0.1:45678"], **"SubjectId": "anonymous"**, "ResponseType": "code", "ResponseMode": "query", "GrantType": "authorization_code", "RequestedScopes": "openid profile email api1", "State": "QI2EYPTPXC5Em7C7Dj9l2A", "UiLocales": null, "Nonce": "Zj81W6UhQv9w_lAmK-anDA", "AuthenticationContextReferenceClasses": null, "DisplayMode": null, "PromptMode": null, "MaxAge": null, "LoginHint": null, "SessionId": "", "Raw": {"response_type": "code", "nonce": "Zj81W6UhQv9w_lAmK-anDA", "state": "QI2EYPTPXC5Em7C7Dj9l2A", "code_challenge": "LdnZafkNy5oI7M42U6mZv2NbKLECh8OXN0NvVVtOBrk", "code_challenge_method": "S256", "client_id": "native.code", "scope": "openid profile email api1", "redirect_uri": "http://127.0.0.1:45678"}, "$type": "AuthorizeRequestValidationLog"}

[07:28:36 Information] IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator
**Showing login: User is not authenticated**

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Start authorize request protocol validation

[07:28:36 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Checking for PKCE parameters

[07:28:36 Debug] IdentityServer4.Validation.AuthorizeRequestValidator
Calling into custom validator: IdentityServer4.Validation.DefaultCustomAuthorizeRequestValidator

[07:28:36 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client native.code succeeded.
brockallen commented 4 years ago

I'm going to guess it's related to the signin scheme you're using for google and how you're processing it on the external callback logic (meaning does it match).

breynolds commented 4 years ago

I saw some posts about that, so I had tried a few things there.

First I left everything defaulted thinking that it should just work that way, but it didn't. That was leaving SignInScheme as it's default in AddGoogle and then in ExternalController, leaving AuthenticateAsync and SignoutAsync both using "IdentityConstants.ExternalScheme"

Second, in the working IdentityServer that did not use ASP.Net Core Identity, we used IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme for all three (SignInScheme, AuthenticateAsync, and SignoutAsync) as was explained in the "Interactive Applications with ASP.NET Core" quickstart. That didn't work either.

Third, I had thought one of the first two would work, but they didn't, so I tried going back to using IdentityConstants.ExternalScheme for AuthenticateAsync and SignoutAsync, and then in AddGoogle, I explicitly set SignInScheme to also be IdentityConstants.ExternalScheme and that didn't work either.

Am I using the wrong scheme, or missing a place where the scheme needs to be set in one of the Startup.cs or ExternalController.cs?

mdmoura commented 4 years ago

I think I am having a similar problem described in the issued I posted (#85).

I am starting the login process from an Angular 9 SPA using oidc-client-js and I am redirected to IS4 login page. I choose to authenticate with Google being redirected to Google login where I have my consent ... I am then redirected to External / Callback where there is a returnUrl to the SPA Client application. However I end up being redirected back to IS4 login page and not SPA login callback.

Either I login with Username / Password or Google I am always successfully authenticated on IS4.

It is just that when using Google I am not redirected back to the SPA client to complete the process.

@breynolds Did you solve your problem? Thank you.