FusionAuth / fusionauth-issues

FusionAuth issue submission project
https://fusionauth.io
91 stars 12 forks source link

OpenId Connect Provider: Joomla + Miniorange and invalid applicationId #548

Closed lamuertepeluda closed 4 years ago

lamuertepeluda commented 4 years ago

OpenId Connect Provider: Joomla + Miniorange and invalid applicationId

Description

I'm developing a React SPA which can login on a FusionAuth tenant using Implict Grant, and a separated node-express server which is using the same application id to perform login using the Authorization Code Grant

So far, so good: everything's working great.

Now we are trying to setup Joomla Miniorange as an additional identity provider, in a way that the aforementioned clients can use the "login with miniorange" feature and use an existing user base for the same application.

After having upgraded to latest fusion auth version, which resolved the problem with the state querystring parameter in #538 , we are now stuck at this screen:

image

Here is the event log

Failed to complete a login for Identity Provider [MiniOrange Test].

The following errors occurred:

{
  "fieldErrors" : {
    "applicationId" : [ {
      "code" : "[invalid]applicationId",
      "message" : "Invalid [applicationId] property. No application exists with an id = [88c91593-f3dd-4e94-a97d-6c51298bac31]."
    } ]
  },
  "generalErrors" : [ ]
}

The applicationId seems correct to me.

Steps to reproduce

Follow steps in https://fusionauth.io/docs/v1/tech/identity-providers/openid-connect/ to setup the Id provider, then attempt login

Expected behavior

I expected a user consent screen, or something to complete the miniorange user registration with FusionAuth, and finally to get the token in my clients. Instead I get the aforementioned errors

Screenshots

Here is a screenshot of our Idp Configuration

idp_config

Platform

Additional context

Using Implicit Grant flow I see the following calls in Chrome inspector

  1. GET <fusionauth>/oauth2/authorize with parameters
    scope: "openid"
    client_id: <my application id>
    state: <a b64encodedstring>
    tenantId: <my tenant id>
    redirect_uri: <my client redirect uri as configured in the application>
    response_type: "id_token token"
    locale: <user locale>
  2. The user clicks on "Login with Miniorange" button, then

    GET <fusionauth>/oauth2/redirect with parameters
    client_id: <my application id>
    identityProviderId: <idp_id>
    state: <state_generated_by_fusionauth_with_lots_of_params>
  3. The URL is a redirection (302) to the configured authorization endpoint for the IdP

    GET <miniorange>/joomlademo1/index.php
    client_id: <client_id_provided_by_miniorange_and_configured_in_idp>
    redirect_uri: <fusionauth>/oauth2/callback
    response_type: code
    scope: profile
    state: <b64 encoded state of step2>

The user performs login with miniorange credentials on the miniorange form On successm miniorange redirects (302) to the redirect_uri

4.

GET <fusionauth>/oauth2/callback
code: <authorization_code>
state: <b64 encoded state of step2>
  1. Step 4 is also a redirect (302) to
    GET <fusionauth>/oauth2/authorize
    client_id: <my application id>
    metaData.device.name: Windows Chrome
    metaData.device.type: BROWSER
    redirect_uri: <my client redirect uri as configured in the application>
    response_type: id_token token
    scope: openid
    state: <a b64encodedstring> // same of step 1
    timezone: Europe/Rome

And here I get the error described at the beginning of the issue and get stuck. 😭

robotdan commented 4 years ago

Thanks for the great detail and recreate steps, that always helps a ton.

Maybe a dumb question, but do you have an application with Id 88c91593-f3dd-4e94-a97d-6c51298bac31 and is it active (not currently disabled) ?

The only way we'd return that error if the application actually did exist, would be if the request was scoped to a tenant that does not contain that application.

So if the X-FusionAuth-TenantId header exists, or the request parameters contain a tenantId request parameter, etc - the validation step will not find the application if the tenantId is not the correct one.

You could paste in the actual request w/ the Base64 encoded state, or DM it to me on the FusionAuth Slack channel so I can see what is in it.

lamuertepeluda commented 4 years ago

@robotdan Yes, the application id is correct, and the application is active in the tenant. If I use the authorize endpoint without attempting the OpenID connect procedure with the 3rd party app, it works perfectly.

The application Id is supplied as:

client_id: 88c91593-f3dd-4e94-a97d-6c51298bac31

as parameter in the authorize request at step 1 described in this issue, together with the tenantId to which it belongs, in order to also get the custom template I've set for that tenant.

GET <fusionauth>/oauth2/authorize

In which request of the above should I check for X-FusionAuth-TenantId to be present? I don't see it in any of the request I'have mentioned. I forgot also to mention that our FusionAuth instance runs in a docker-container behind nginx as reverse proxy. I hope that is not blocking this header, althoug the tenantId is supplied in the query string.

The nginx configuration is:

        proxy_pass http://127.0.0.1:9011;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $remote_addr;
        if ($http_referer ~ ^android-app://org.telegram.messenger) {
                set $esb "https://longisland.polito.it";
        }
        proxy_set_header Referer $esb;
        proxy_cache_bypass $http_upgrade;
        proxy_intercept_errors on;
        recursive_error_pages on;

Before opening the issue, since I had to upgrade the FusionAuth container, I rebuilt the index: I had tried without rebuilding the index, then attempted this to check if it helped solving this problem, but the result is the same.

robotdan commented 4 years ago

In which request of the above should I check for X-FusionAuth-TenantId to be present? I don't see it in any of the request I'have mentioned.

I don't think you're sending it - I brought it up just in case you were sending it by accident.

I took another look at this - I may have identified the issue. Not sure if you can hack this to test the theory, but if you able to add &client_id=88c91593-f3dd-4e94-a97d-6c51298bac31 to the request URL back to the FusionAuth endpoint /oauth2/callback I think it will work.

So in your step 4, it would be modified to look like this:

GET <fusionauth>/oauth2/callback
client_id: 88c91593-f3dd-4e94-a97d-6c51298bac31
code: <authorization_code>
state: <b64 encoded state of step2>

If I'm correct, this error was introduced in https://github.com/FusionAuth/fusionauth-issues/issues/538. I'll try to recreate, and if I can prove the issue I'll try to get a patch out shortly to resolve the issue.

Thanks for letting us know and providing excellent detail and recreate steps.

As a side note, if you can avoid the implicit grant you should, it is vulnerable to JavaScript attacks which can steal your access token. Using the Authorization Code Grant with PKCE is a better choice, or if you have to use the implicit, adding PKCE is a compromise. The implicit grant trades perceived simplicity of implementation for SPAs for security.

We have a bunch of documented login flows if you didn't find these already, we have a few recommended approaches for single page webapps. https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows

robotdan commented 4 years ago

I was able to replicate the issue in a test, this will go out in the next patch release. Thanks for reporting the issue!