An error was encountered while handling the remote login.

  • ABP Framework version: v5.1.3
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): MVC
  • Exception message and stack trace: 2022-02-21 20:00:53.944 +00:00 [ERR] An unhandled exception has occurred while executing the request. System.Exception: An error was encountered while handling the remote login. ---> Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'. at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest) at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync() --- End of inner exception stack trace --- at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler1.HandleRequestAsync() at IdentityServer4.Hosting.FederatedSignOut.AuthenticationRequestHandlerWrapper.HandleRequestAsync() at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)`
  • Steps to reproduce the issue:"
  • Deployed the web and public web application to Azure (works on development).
  • Simply click on the "Login" on the public site.
  • Can try it life here: https://www.scrapi.dev/

URL configuration is correct, followed guide on identity server deployment and couldn't find anything wrong. Not sure what I am missing. This is a direct deployment from the template before any updates. The admin password was changed so would be happy to share that if the config needs to be reviewed.


1 Answer(s)
  • Solved with information provided here: https://stackoverflow.com/a/58927285/564726

Trying to use the ffdc-sample-csharp solution. I set up my application in FFDC. The B2B side works ok. But I'm having trouble with the B2C side using client id/secret (or JWT private token). After I type in ffdcuser1 and its password, it fails after that. Error text:

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]

An unhandled exception has occurred while executing the request.

System.Exception: An error was encountered while handling the remote login.

---> System.Exception: Correlation failed.

--- End of inner exception stack trace ---

at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()

at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Paul McNamara

@mackie1001

Do you have the exact log message to hand?

I have a very confusing problem. In my login handler I've explicitly set my claims principal but when calling SignInAsync it keeps throwing this exception: InvalidOperationException: sub claim is missing from IdentityServer4.Extensions.PrincipalExtensions.GetSubjectId(IIdentity identity) in PrincipalExtensions.cs.

I can't figure out what I'm missing. Any ideas?

My handler code is below:

        [HttpGet("user-sessions/new")]
        public async Task<IActionResult> GetNewUserSessionAsync([FromQuery]string ReturnURL)
        {
            if (_interactionService.IsValidReturnUrl(ReturnURL) == false)
            {
                // Security concern
                throw new ArgumentOutOfRangeException(nameof(ReturnURL)
                    , nameof(ReturnURL) + " is not a valid URL");
            }

            // attempt to login via Windows
            var loginResult = await HttpContext.AuthenticateAsync("Windows");
            if(loginResult.Succeeded)
            {
                var windowsIdentity = (WindowsIdentity)loginResult.Principal.Identity;
                var sid = windowsIdentity.User.Value;
                var username = windowsIdentity.Name;

                var newIdentity = new ClaimsIdentity("Windows");
                newIdentity.AddClaim(new Claim(JwtClaimTypes.Subject, sid));
                newIdentity.AddClaim(new Claim(JwtClaimTypes.Name, username));
                var principal = new ClaimsPrincipal(newIdentity);

                await HttpContext.SignInAsync("Windows", principal);

                return Redirect(ReturnURL);
            }
            else
            {
                return Challenge("Windows");
            }
        }

An error was encountered while handling the remote login.

@mackie1001 That's the error - the "Discovery client couldn't be found" is my own text, the real exception starts on the next line. I'm just using the DiscoveryClient to get the TokenEndpoint

Dan Anselm

@dan.rockcoll_gitlab

Does IS4 work in a trust scenario with an external IdP? My scenario is that IS4 holds the identities, but needs to trust AWS IAM so that IAM can issue tokens for accessing AWS resources based on the token issued by IS4. I think this means IAM is just another client to IS4, but I am guessing the communication between the two to enable the trust is a bit more than the usual client chatter with IS4. I have looked through the docs, but they only cover the scenario where the external IdP holds the identities.

An error was encountered while handling the remote login.

Eugenio Favalli

@eugeniofavalli_twitter

hello, with windows authentication how do you get the AD SID of the user?

@eugeniofavalli_twitter take a look at the code sample I pasted above. the lines you want are:

var windowsIdentity = (WindowsIdentity)loginResult.Principal.Identity;
                var sid = windowsIdentity.User.Value;

An error was encountered while handling the remote login.

Eugenio Favalli

@eugeniofavalli_twitter

@CrossBound thanks, solved!

Daniel Matthews

@knight1219

Hi all! So I have a question: We use IdSrv4 as an auth gateway for all of our internal applications that we build. Each app gets a client that only it uses. We have a requirement that our gateway have an api call that will serve all of our clients, so a good bearer token from app1 and a different token from app2 will still be able to access this same api. Any tips on how I would configure this?

The "UTF-8" error above? A proxy was getting in the way and putting dumb content in the way. Resolved.

Paul McNamara

@mackie1001

@eratos It's likely due to it trying to use HTTPS instead of HTTP

If you put that URL into your browser what do you get?

Hi Paul - I definitely had https and I can reach the discovery endpoint in my browser

I have added default credentials to the HttpClient I use in the app, and to the DiscoClient and Token client calls I make.

This is making me good progress - however I have one more that I don't know how to fix because it doesn't call into my code.

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden]'.
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HLOG882M7JIN", Request id "0HLOG882M7JIN:00000005": An unhandled exception was thrown by the application.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII is hidden]'.
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
   at IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

If I turn the proxy off then I do not get this error and my website works fine. With the proxy on, this is the error I'm getting - but I can't find anything to attach proxy credentials to.

Is there something in here I can do?

            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>

I believe this is where the API is trying to access the introspection endpoint?

I'm trying IntrospectionBackChannelHandler

Turns out I actually needed this in the API

                    options.JwtBackChannelHandler = new HttpClientHandler
                    {
                        DefaultProxyCredentials = CredentialCache.DefaultCredentials
                    };

and this in the app

                options.BackchannelHttpHandler = new HttpClientHandler
                {
                    DefaultProxyCredentials = CredentialCache.DefaultCredentials
                };

Hope that helps someone in the future!

Shane Holder

@shaneholder

Hi, I'm using the identityserver 4 quickstart to prototyping an external identity provider which uses the code flow and I'm hitting an exception after the provider has returned the code.

 Microsoft.IdentityModel.Tokens.SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''."
 System.Exception: An error was encountered while handling the remote login. ---> Microsoft.IdentityModel.Tokens.SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''."
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.ValidateToken(String idToken, AuthenticationProperties properties, TokenValidationParameters validationParameters, JwtSecurityToken& jwt)
   at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at IdentityServer4.Hosting.FederatedSignOut.AuthenticationRequestHandlerWrapper.HandleRequestAsync() in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Hosting\FederatedSignOut\AuthenticationRequestHandlerWrapper.cs:line 38
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context) in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\src\Hosting\BaseUrlMiddleware.cs:line 36
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

My oidc config

.AddOpenIdConnect("oidc", "OpenID Connect", options =>
                                {
                                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                                    options.SaveTokens = true;

                                    options.Authority = "https://anauthserver/";
                                    options.ClientId = "myclientid";
                                    options.ClientSecret = "nunya";
                                    options.ResponseType = OpenIdConnectResponseType.Code;
                                    options.Scope.Clear();
                                    options.Scope.Add("extended");
                                    options.Scope.Add("openid");
                                    options.TokenValidationParameters = new TokenValidationParameters
                                    {
                                        ValidateIssuer = true
                                    };
                                });

I think the next step is supposed to be redeeming the code for the id_token right? I was wondering why it is trying to do something with FederatedSignOut.

Shane Holder

@shaneholder

The external server I'm authenticating against is spring boot and there seems to be some discussion on github where it is suggested that the code flow wont return an spring-projects/spring-security#6965. Is there a way to configure IdentityServer/AspNetAuth to not need the id_token?

Paul McNamara

@mackie1001

The code in the middleware checks to see if there is an id_token before going down that path

So I'm not sure how it's getting into that state

Actually I tell a lie, it assumes the token endpoint returns an id_token

So I'm guessing your remote IDP isn't actually OIDC compliant. You may need to use the OAuth2 middleware instead

Hey guys,

Can anyone help me with the following?
I have to implement a STS and I was thinking to use the IdentityServer 4 solution, since I used already the 3rd and worked like a charm.
Although a college asked me why not use "Microsoft identity platform". After reading Microsoft documentation, I got the impression that solution is exclusive to Azure.
Do any of you know about this "Microsoft identity platform" (link: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-overview) and can explain me if this is Microsoft's solution of identity server, is kind of competitor, or is something else.

Thanks

Paul McNamara

@mackie1001

Azure AD is their SaaS/cloud directory and SSO offering

And it implements OpenID Connect

So yes, it can work similarly to a service you might create yourself using identityserver4

Ghost

@ghost~5d3a8fb5d73408ce4fc6ff69

Hi Anybody meets one issue that the client cannot redirect after allowed on identityserver4

An error was encountered while handling the remote login.

Eugenio Favalli

@eugeniofavalli_twitter

hello again, do you know how to set custom errors so they show in the error page

Zbyněk Novotný

@mrclayman

Hi all, I am pretty new to IS4 and auth in general, so please bear with me. I'm currently working on a microservice-based backend for a videogame and I was tasked with securing the API with access tokens. I would like to use IS4 as the authorization entity, but perhaps in a somewhat non-traditional way. The game client uses Steam as the authentication layer, so it is capable of obtaining a so-called "session ticket" that the server backend can verify with online Steam API to make sure the client owns, is allowed and is in fact currently playing the game at the moment. So, what I am trying to achieve is to have IS4 issue an access token for a user whose session ticket is successfully validated with Steam. My intuition says I should probably devise my own custom authentication scheme and implement my own authentication handler, but as I said above, I have no real experience using IS4 to speak of, so I am getting a little lost. If anybody could give me some pointers or outline the steps I need to take, I would be very grateful. TIA. :blush:

Paul McNamara

@mackie1001

@mrclayman Sounds like a good case for using a custom grant type

It could take a Steam session ticket, validate it and then if successful, issue a token

Zbyněk Novotný

@mrclayman

Thanks for the tip, @mackie1001 . I had the impression that the implicit grant type was the appropriate choice, but I will definitely look into this.

Paul McNamara

@mackie1001

implicit is browser-based which I'm guessing you won't want in your scenario

Zbyněk Novotný

@mrclayman

Ah, all right. Thanks again for the suggestion, @mackie1001 . Much appreciated. :slight_smile:

We have been using IS4 for about 6 months, and want to ensure that we are aligning with best practices as much as possible. The scenario that we are currently working on is as follows: USER-->WebApp-->SecuredEndPoints. The user workflow is in the form of a wizard, where the interface walks the user through a muti-step process. We have secured the front end such that a user cannot access it without first being authenticated and authorized via IS4. Once they are authorized, we want them to be able to complete the wizard. While walking through the wizard, multiple secured endpoints will be encountered (via IS4). Each of these endpoints are accessed from many different applications and wizards. The front end and all of the secured endpoints currently have different scopes defined, which correspond to different AD groups. Our desire is to only have to put users in a single AD group in order for them to be able to run through the entire wizard....thus the reason we added the security check at the beginning of the flow within the web app. So, the question is....what is the best approach for accessing the back-end secured endpoints, where we only have to add a user to one AD group? BTW, initially, we queried AD for user group membership (i.e. GetMembers(true).FirstOrDefault) with the useRecursion flag set to true, but we found this to have significant performance implications; so, we turned it back off. Thanks in advance for any help afforded!

Paul McNamara

@mackie1001

Authorization checks should not occur in IS4 so you'd have to enforce this in each API

Which unfortunately does mean checking your source of truth for those permissions

But if performance is an issue then you could look at temporary caching

Or even have a permissions service with very fast response times that receives an event feed from AD and invalidates cached values as things change