FusionAuth
    • Home
    • Categories
    • Recent
    • Popular
    • Pricing
    • Contact us
    • Docs
    • Login

    OIDC: Identity Provider doesn't recognize authorization code

    Scheduled Pinned Locked Moved Unsolved
    Q&A
    2
    2
    786
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      piotr
      last edited by

      I'm trying to set up an external IdP using OpenID Connect, with my own login form.

      It works quite well, except for the last step. The authorization code I received in the callback does not seem to be useful as an exchange for an access token.

      Setup

      • Identity Provider: ory.sh (Ory Hydra)
      • FusionAuth version: 1.30.1

      Configuration

      Settings, the Identity Provider:

      • Scopes: email name openid offline offline_access
      • Redirect URIs: https://xxx.fusionauth.io/oauth2/callback
      • Supported OAuth2 flows: client_credentials, authorization_code, refresh_token
      • Response types: id_token, token, code
      • Authentication method: client_secret_post

      Identity Provider in FusionAuth (Generic OpenID Connect):

      • Client Id, Client Secret - as provided by IdP
      • Client authentication: client_secret_post
      • Authorization endpoint: https://xxx.projects.oryapis.com/oauth2/auth
      • Token endpoint: https://xxx.projects.oryapis.com/oauth2/token
      • Userinfo endpoint: https://xxx.projects.oryapis.com/userinfo
      • Scope: name email openid
      • Others: No reconcile lambda, debug enabled
      • Enabled to one application with enabled "Create registration"

      Steps to reproduce

      1. Request to https://xxx.fusionauth.io/oauth2/authorize with query parameters:
      • client_id= <application ID enabled in the IdP config>
      • redirect_uri= <URL encoded, own callback>
      • response_type=code
      • tenantId=<tenant ID that has the application enabled in the IdP config>
      • scope= URL encoded "openid offline_access"
      • idp_hint=<ID of the Identity Provider configuration>
      1. Have been redirected to Ory, got the authorization page, confirmed authorization for scope: email, name, openid.

      2. Got redirection to the callback provided in point 1 as redirect_uri, with query parameters:

      • code=*** 43-character long code, looks like Base64 plus - and _
      • userState=Authenticated
      • locale=en_GB

      Confirmed in Ory web console that FusionAuth is properly listed as an authorized OAuth2 application with correct scope.

      All looks good so far.

      1. As the next step, I tried to exchange the 43-character long code for FusionAuth's access token (JWT):

      Request POST to https://xxx.fusionauth.io/api/identity-provider/login with Content-Type: application/json and body:

      {
          "applicationId": "<FusionAuth's application ID>",
          "data": {
              "code": "43-character long code ",
              "redirect_uri": "same as redirect_uri from point 1"
          },
          "identityProviderId": "FusonAuth's ID of the IdP configuration"
      }
      
      1. Response: HTTP 401:
      {"generalErrors":[
        {"code":"[ExternalAuthenticationException]OpenIDConnectToken","message":"A request to the OpenID Connect Token API has failed. Unable to complete this login request."}
        ]}
      
      1. Event Log:
      The request to the [https://xxx.projects.oryapis.com/oauth2/token] endpoint failed. Status code [400].
      
      Error response is 
      {
        "error" : "invalid_grant",
        "error_description" : "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. not_found"
      }
      

      Investigation, findings

      1. I verified the correctness of the Identity Provider by implementing a simple OIDC flow with the same client configuration in Ory, without FusionAuth, and it worked as expected. Conclusion: problems are not caused by Ory.

      2. Created my own public endpoint where I could see request details, let's call it /middleman
        When replaced Ory's /oauth2/token with /middleman I discovered that FusionAuth does one extra and unexpected call to /oauth2/token between point 2 and point 3 above, i.e., after receiving successful redirection from Ory (with code apparently) and before sending the result to my callback.
        This alone is not a problem yet. I guess FusionAuth keeps communication with Ory as an internal state referred to by its own token. Fine.
        But then, when I call http://xxx.fusionauth.io/api/identity-provider/login with data.code equal to the 43-character code I receive to the callback, FusionAuth seems to send that exact code to Ory. Obviously, Ory does not know what it is and returns an error.
        Conclusion: Ory returns the correct authorization_code, but I have no access to it, moreover, Fusionauth "consumes" this code for a mysterious extra call, without any visible result of it, like access/refresh tokens kept in the internal state.

      Questions

      1. Why FusionAuth calls IdP's /oauth2/token before it calls my callback if it does not keep access/refresh tokens?

      2. What is this 43-character code FusionAuth sends to the callback if I can't use it for anything? Most importantly, I can't use it for fusionauth.io/api/identity-provider/login.

      danD 1 Reply Last reply Reply Quote 1
      • danD
        dan @piotr
        last edited by

        @piotr

        1.30.1

        This is quite an old version of FusionAuth, just FYI.

        Why FusionAuth calls IdP's /oauth2/token before it calls my callback if it does not keep access/refresh tokens?

        FusionAuth does keep the refresh token.

        What is this 43-character code FusionAuth sends to the callback if I can't use it for anything? Most importantly, I can't use it for fusionauth.io/api/identity-provider/login.

        The login API and the Authorization code grant are two separate ways of logging the same user in. They have different strengths and weaknesses, but in general you can't move between them.

        You should be able to provide that 43 character code to the /oauth2/token endpoint and get back a response.

        Hope this helps!

        --
        FusionAuth - Auth for devs, built by devs.
        https://fusionauth.io

        1 Reply Last reply Reply Quote 0
        • First post
          Last post