Base solution for your next web application
Open Closed

OpenId Help #4033


User avatar
0
cmthomps created

I'm trying to integrate with an OpenId server and I'm new to the process. I've enabled the openId authentication provider in appsettings.json. When I click the openid button on the login screen it takes me to the openid server login page. After login, I see an error that says:

Error invalid_grant There was an error processing your request.

A redirect_uri can only be used by implicit or authorization_code grant types.

Does anyone know if this is an issue with how the application is configured or does this seem like a server problem? I've tried changing the AllowedGrantTypes in appsettings.json to include "implicit" and "authorization_code" but I see the same error.

Thanks, Craig


13 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @cmthomps,

    I'm attaching a sample configuration screenshot, it might help you.

  • User Avatar
    0
    cmthomps created

    Same result. I had already had those same settings in my appsettings.json file (this is a core project). The openid login redirects to the proper openId authority but after I login, I get the "invalid_grant - A redirect_uri can only be used by implicit or authorization_code grant types." error on the openid server (not in my aspnetzero project).

    "OpenId": {
          "IsEnabled": "true",
          "Authority": "https://sb-auth.smarthealthit.org/",
          "ClientId": "4*******",
          "ClientSecret": "********"
        }
    
  • User Avatar
    0
    aaron created
    Support Team

    Can you try adding this in Startup.cs?

    app.UseOpenIdConnectAuthentication(x =>
    {
        x.AuthenticationScheme = "oidc";
        x.Authority = "https://sb-auth.smarthealthit.org/";
        x.AutomaticAuthenticate = true;
        x.CallbackPath = new PathString("/services/oauth2/success"); // redirect_uri
        x.ClientId = "4*******";
        x.ClientSecret = "********";
        x.ResponseType = "code";
        x.Scope.Add("email");
        x.Scope.Add("openid");
        x.Scope.Add("profile");
    });
    

    Disclaimer: I haven't tried this myself.

  • User Avatar
    0
    cmthomps created

    I've tried another OpenId server. With both Okta and Auth0, in the ExternalLoginCallback method in the AccountController this line of code come back with a null result. Google works. But any of the openId connect servers I've tried doesn't.

    var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();
    
  • User Avatar
    0
    cmthomps created

    One more piece of information, after I get the null result in my previous post. The application redirects to login. When I look at the cookies, I see what is in the attached image. Something is coming back from the OpenId Connect server. Just not sure where the issue is.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @cmthomps,

    Did you have a chance to try OpenID with azure ? Because we only tested it with azure. Do venders you use have any documentation for using their service with OpenId connect ?

  • User Avatar
    0
    cmthomps created

    Thank you. I'm seeing the same result with Azure OpenId Connect GetExternalLoginInfoAsync returns null but I see similar cookies to the screenshot in my previous post.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @cmthomps,

    Which version of AspNet Zero & ABP do you use ? There might be a problem/bug we have fixed.

    If you are using latest version, we can prepare and send you a sample project using OpenIdConnect.

    Thanks.

  • User Avatar
    0
    cmthomps created

    That would be great. I'd appreciate it. I downloaded the latest version (4.6) of aspnetzero for this test because I was wondering if the version we were working with had a bug. I'm not sure what version of abp comes with 4.6. I'd be happy to send you my test project as well.

  • User Avatar
    0
    cmthomps created

    Update on this thread. I finally got all my issues ironed out. But, I'm confused a bit. I downloaded a new .NET Core/jQuery solution from aspnetzero.com on 10/24. In that version, the AccountController.cs has the following method:

    [UnitOfWork]
            public virtual async Task<ActionResult> ExternalLoginCallback(string returnUrl, string authSchema, string remoteError = null)
            {
                returnUrl = NormalizeReturnUrl(returnUrl);
                
                if (remoteError != null)
                {
                    Logger.Error("Remote Error in ExternalLoginCallback: " + remoteError);
                    throw new UserFriendlyException(L("CouldNotCompleteLoginOperation"));
                }
    
                var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync(authSchema);
                if (externalLoginInfo == null)
                {
                    Logger.Warn("Could not get information from external login.");
                    return RedirectToAction(nameof(Login));
                }
    
                await _signInManager.SignOutAsync();
    
                var tenancyName = GetTenancyNameOrNull();
    
                var loginResult = await _logInManager.LoginAsync(externalLoginInfo, tenancyName);
    
                switch (loginResult.Result)
                {
                    case AbpLoginResultType.Success:
                        await _signInManager.SignInAsync(loginResult.Identity, false);
                        return Redirect(returnUrl);
                    case AbpLoginResultType.UnknownExternalLogin:
                        return await RegisterForExternalLogin(externalLoginInfo);
                    default:
                        throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(
                            loginResult.Result,
                            externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email) ?? externalLoginInfo.ProviderKey,
                            tenancyName
                        );
                }
            }
    

    The problematic line of code was:

    var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync(authSchema);
    

    The authSchema parameter was what was causing the problem. When running with OpenId, that parameter has a value of "OpenIdConnect". However, in digging into the underlying MSFT code that parameter is:

    <param name="expectedXsrf">Flag indication whether a Cross Site Request Forgery token was expected in the current request.</param>
    

    When I removed the parameter from GetExternalLoginInfoAsync, the authentication started working. The thing that is baffling to me is that in looking at the code currently on GitHub, that parameter is not there... Not exactly sure what is going on. The code on GitHub looks right but it's different from what I downloaded via aspnetzero.com the other day.

    Hope this helps someone else...

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @cmthomps,

    Thank you very much for your explanation. Can you share the code link on github ?

  • User Avatar
    0
    cmthomps created

    I'd be happy to share what I have. One piece of additional info. The line of code with the authSchema parameter came from a Asp.Net Boilerplate project. I had downloaded it when I was having problems to try a different set of code. The AspNetZero project I downloaded does not use the authSchema.

    Here is a link to a gist that allowed me to login with a Core 1.0/1.1 AspNetZero project. It represents a change to the AuthConfigurer.cs. I don't think this change is necessary for .NET Core 2.0 based AspNetZero projects.

    https://gist.github.com/cmthomps/53645f3ca5f7af3feebb8f4766c6362d
    
  • User Avatar
    0
    aaron created
    Support Team

    The authSchema parameter was what was causing the problem.

    PR: https://github.com/aspnetboilerplate/module-zero-core-template/pull/138