aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.41k stars 2.11k forks source link

Unable to override oauth domain in v6 using documented method #12849

Open alex-breen opened 7 months ago

alex-breen commented 7 months ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Amplify CLI

Environment information

``` # Put output below this line System: OS: Windows 11 10.0.22621 CPU: (6) x64 Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz Memory: 4.09 GB / 15.94 GB Binaries: Node: 18.18.0 - C:\Program Files\nodejs\node.EXE npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD Browsers: Chrome: 120.0.6099.216 Edge: Chromium (120.0.2210.133) Internet Explorer: 11.0.22621.1 npmPackages: @aws-amplify/ui-react: ^6.1.1 => 6.1.1 @aws-amplify/ui-react-internal: undefined () @aws-amplify/ui-react-storage: ^3.0.10 => 3.0.10 @types/react: ^18.2.43 => 18.2.47 @types/react-dom: ^18.2.17 => 18.2.18 @vitejs/plugin-react: ^4.2.1 => 4.2.1 aws-amplify: ^6.0.12 => 6.0.12 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () eslint: ^8.55.0 => 8.56.0 eslint-plugin-react: ^7.33.2 => 7.33.2 eslint-plugin-react-hooks: ^4.6.0 => 4.6.0 eslint-plugin-react-refresh: ^0.4.5 => 0.4.5 react: ^18.2.0 => 18.2.0 react-dom: ^18.2.0 => 18.2.0 vite: ^5.0.8 => 5.0.11 ```

Describe the bug

When I use Amplify.configure to update the oauth domain, social sign in fails.

I am following the method described here (and elsewhere): https://docs.amplify.aws/react/build-a-backend/troubleshooting/migrate-from-javascript-v5-to-v6/#step-3-upgrade-amplify-cli-version-and-configuration-file

Amplify.configure() will now accept either the config JSON file or a strongly typed configuration object. Therefore, if you need to add additional configuration, you will call configure twice: once with the contents of amplifyconfiguration.json, and then again using Amplify.getConfig() plus any additions. Keep in mind that any call to configuration will fully override previous configurations, so pay special attention to nested configurations

When I implement this way:

import { Amplify } from 'aws-amplify';
import amplifyconfig from './amplifyconfiguration.json';

Amplify.configure(amplifyconfig);
Amplify.configure({
  ...Amplify.getConfig(),
  Auth: {
    ...Amplify.getConfig().Auth,
    Cognito: {
      ...Amplify.getConfig().Auth.Cognito,
      loginWith: {
        ...Amplify.getConfig().Auth.Cognito.loginWith,
        oauth: {
          ...Amplify.getConfig().Auth.Cognito.loginWith.oauth,
          domain: 'sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com'
        }
      }
    }
  }
})

What I see is the the browser attempts a url like this: https://sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com/oauth2/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F&response_type=code&client_id=27s2qe07qgpp0mf7083dian9ua&identity_provider=Google&scope=phone%20email%20openid%20profile%20aws.cognito.signin.user.admin&state=PRLNO8KkeoljTbg6AlgDgoJcObrj9d9F&code_challenge=u3HeGFEvtCtpWmfvOmPnaJKtIs9MiteXsrH7pzsdzOY&code_challenge_method=S256

And then redirects immediately back: http://localhost:3000/?code=92fe14a0-b502-4e98-8500-908eb18893da&state=PRLNO8KkeoljTbg6AlgDgoJcObrj9d9F

Rather than trying to authenticate with google through the following steps:

- https://accounts.google.com/o/oauth2/v2/auth?client_id= ...
- https://sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com/oauth2/idpresponse?state= ....
- http://localhost:3000/?code= ....

However, if I instead modify amplifyconfiguration.json (similar to the method used in v5) it works as expected:

import { Amplify } from 'aws-amplify';
import amplifyconfig from './amplifyconfiguration.json';

const updatedAmplifyConfig = {
  ...amplifyconfig,
  oauth: {
    ...amplifyconfig.oauth,
    domain: 'sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com'
  }
}
Amplify.configure(updatedAmplifyConfig);

What is interesting (or confounding) is that if I compare the result for Amplify.getConfig() in both cases the JSON is identical. Note, nothing is logged to the browser console.

Expected behavior

Please see description.

Reproduction steps

Please see description.

Code Snippet

Please see code in description for comparison case. Below is my amplifyconfiguration.json file with a domain that should fail if unmodified.

// Put your code below this line.
{
  "aws_project_region": "us-east-1",
  "aws_cognito_identity_pool_id": "us-east-1:0598a33f-9357-4ba8-9cb2-876da7c9bb85",
  "aws_cognito_region": "us-east-1",
  "aws_user_pools_id": "*************",
  "aws_user_pools_web_client_id": "*************",
  "oauth": {
    "domain": "yoda.amazoncognito.com",
    "scope": [
      "phone",
      "email",
      "openid",
      "profile",
      "aws.cognito.signin.user.admin"
    ],
    "redirectSignIn": "http://localhost:3000/",
    "redirectSignOut": "http://localhost:3000/",
    "responseType": "code"
  },
  "federationTarget": "COGNITO_USER_POOLS",
  "aws_cognito_username_attributes": [
    "EMAIL"
  ],
  "aws_cognito_social_providers": [
    "GOOGLE"
  ],
  "aws_cognito_signup_attributes": [
    "EMAIL"
  ],
  "aws_cognito_mfa_configuration": "OFF",
  "aws_cognito_mfa_types": [
    "SMS"
  ],
  "aws_cognito_password_protection_settings": {
    "passwordPolicyMinLength": 8,
    "passwordPolicyCharacters": []
  },
  "aws_cognito_verification_mechanisms": [
    "EMAIL"
  ]
}

Log output

No logs on console.log. ``` // Put your logs below this line ```

aws-exports.js

/ eslint-disable / // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = { "aws_project_region": "us-east-1", "aws_cognito_identity_pool_id": "", "aws_cognito_region": "us-east-1", "aws_user_pools_id": "", "aws_user_pools_web_client_id": "*****", "oauth": { "domain": "sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com", "scope": [ "phone", "email", "openid", "profile", "aws.cognito.signin.user.admin" ], "redirectSignIn": "http://localhost:3000/", "redirectSignOut": "http://localhost:3000/", "responseType": "code" }, "federationTarget": "COGNITO_USER_POOLS", "aws_cognito_username_attributes": [ "EMAIL" ], "aws_cognito_social_providers": [ "GOOGLE" ], "aws_cognito_signup_attributes": [ "EMAIL" ], "aws_cognito_mfa_configuration": "OFF", "aws_cognito_mfa_types": [ "SMS" ], "aws_cognito_password_protection_settings": { "passwordPolicyMinLength": 8, "passwordPolicyCharacters": [] }, "aws_cognito_verification_mechanisms": [ "EMAIL" ] };

export default awsmobile;

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

cwomack commented 7 months ago

Hello, @alex-breen 👋. Want to ask a few questions about this to understand what's going on a little better. Are you trying to do 2 separate sign-ins with different domains or just a single domain? And are you trying to manually update the config or have you update via the CLI at this point?

alex-breen commented 7 months ago

Hi @cwomack.

In my example, the amplifyconfiguration.json has a fake domain that will fail. This was set originally by the CLI.

  "oauth": {
    "domain": "yoda.amazoncognito.com",

I am trying to override the oauth domain by calling Amplify.configure with the new value at runtime.

In my real app, I am overriding the domain value from the default cognito domain to a custom (branded) one (as configured on Cognito). Also, and less important, I override in my test environment for localhost, but keep the Cognito (dev) domain as is.

nadetastic commented 6 months ago

Hi @alex-breen can you clarify what error message you are seeing when social sign in fails? And at exactly which step it seems to fail at?

alex-breen commented 6 months ago

Hi @nadetastic - No error message on failure, in console logs or network logs.

What I see is the the browser attempts a url like this: https://sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com/oauth2/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F&response_type=code&client_id=27s2qe07qgpp0mf7083dian9ua&identity_provider=Google&scope=phone%20email%20openid%20profile%20aws.cognito.signin.user.admin&state=PRLNO8KkeoljTbg6AlgDgoJcObrj9d9F&code_challenge=u3HeGFEvtCtpWmfvOmPnaJKtIs9MiteXsrH7pzsdzOY&code_challenge_method=S256

And then redirects immediately back: http://localhost:3000/?code=92fe14a0-b502-4e98-8500-908eb18893da&state=PRLNO8KkeoljTbg6AlgDgoJcObrj9d9F

Rather than trying to authenticate with google through the following steps:

- https://accounts.google.com/o/oauth2/v2/auth?client_id= ...
- https://sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com/oauth2/idpresponse?state= ....
- http://localhost:3000/?code=92fe14a0-b502-4e98-8500-908eb18893da&state=PRLNO8KkeoljTbg6AlgDgoJcObrj9d9F
nadetastic commented 6 months ago

@alex-breen thank you for confirming! This sounds similar to the issue at https://github.com/aws-amplify/amplify-js/issues/4044 where after the initial sign in on the social provider (ex Google) Cognito Hosted UI continues to remember the session and auto authenticates you with the provider and doesn't display the Google login screen. Does this sound correct?

alex-breen commented 6 months ago

Hi @nadetastic - it might be similar (I found it a bit hard to follow the various comments on https://github.com/aws-amplify/amplify-js/issues/4044). If I've previously signed in with Google, then yes, it immediately goes back to the app, but without the info it needs to proceed.

cwomack commented 6 months ago

@alex-breen, can you share what the frontend code looks like where you're signing in? Also, can you clarify what the root problem/error is here? Is it that you're expecting the redirect sign in to go directly to Google and have it ask to sign in with Google?

Can you also share your sign out code and network requests when signOut is called?

alex-breen commented 6 months ago

@nadetastic - I'm expecting a successful signin on Google to result in the app getting user credentials in the redirect.

In order to reproduce it cleanly, the code is close to the documentation's plain quickstart tutorial.

So the core of the app is just this:

App.jsx

  return (
    <div>
      <Authenticator>
        {({ signOut, user }) => (
          <div>
            <h1>Hello {user.username}</h1>
            <button onClick={signOut}>Sign out</button>
            <Page />
          </div>
        )}
      </Authenticator>
    </div>
  )

main.jsx

import { Amplify } from 'aws-amplify';
import amplifyconfig from './amplifyconfiguration.json';

Amplify.configure(amplifyconfig);
Amplify.configure({
  ...Amplify.getConfig(),
  Auth: {
    ...Amplify.getConfig().Auth,
    Cognito: {
      ...Amplify.getConfig().Auth.Cognito,
      loginWith: {
        ...Amplify.getConfig().Auth.Cognito.loginWith,
        oauth: {
          ...Amplify.getConfig().Auth.Cognito.loginWith.oauth,
          domain: 'sandboxauth167bef521-67bef521-dev.auth.us-east-1.amazoncognito.com'
        }
      }
    }
  }
})
nadetastic commented 5 months ago

@alex-breen thanks for the context - When you said the following:

I'm expecting a successful signin on Google to result in the app getting user credentials in the redirect.

are you not getting credentials? For example if you call getCurrentUser() or fetchAuthSession() what is the output?

alex-breen commented 5 months ago

@nadetastic - no credentials. Auth calls like getCurrentUser() fail. It just redirects back to the redirect link (with code).

nadetastic commented 5 months ago

@alex-breen one potential issue is that the hosted ui endpoint you are trying to use is not configured to work the the userpool/userpool client that you are defining through Amplify.configure()

Could you elaborate more on that? Im also a bit curious on your use case and the reason to only override the hosted ui endpoint

alex-breen commented 5 months ago

@nadetastic - I override the endpoint so that I can use a custom domain name.

cwomack commented 4 months ago

@alex-breen, I know this was opened before this version was released... but could you see if upgrading to a more recent version of Amplify (anything v6.0.23+) resolves this issue? We made some updates to how the OAuth flow resolves when redirecting back to the app that could impact this.

alex-breen commented 4 months ago

Hi @cwomack - I tried with Amplify 6.0.28, and I still get the issue. In my test I modify oauth: domain to a bad value, but override with a correct value (using same code as above in the thread). But it is still requesting the bad url.

A few things:

├── @aws-amplify/ui-react-storage@3.0.18 ├── @aws-amplify/ui-react@6.1.8 ├── @types/react-dom@18.2.18 ├── @types/react@18.2.47 ├── @vitejs/plugin-react@4.2.1 ├── aws-amplify@6.0.28 ├── eslint-plugin-react-hooks@4.6.0 ├── eslint-plugin-react-refresh@0.4.5 ├── eslint-plugin-react@7.33.2 ├── eslint@8.56.0 ├── react-dom@18.2.0 ├── react@18.2.0 └── vite@5.0.11

cwomack commented 1 month ago

@alex-breen, it appears that the way you're using the Amplify.getConfig() and configuring things properly, but oauth.domain is not potentially being overwritten in the expected way. We're going to investigate this as a bug at this point and we'll let you know if there are further questions or updates.

nicolashuby commented 1 month ago

I encountered the same issue with a react app. Another team does not have the issue with a Vue.js app