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.43k stars 2.13k forks source link

`AuthUserPoolException` when using a custom tokenProvider #13018

Closed ryanwalters closed 4 months ago

ryanwalters commented 9 months ago

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

None

Environment information

`npx envinfo` did not work on my system. The below is using `npx --no-install next info`: ``` # Put output below this line Operating System: Platform: win32 Arch: x64 Version: Windows 10 Pro Binaries: Node: 20.11.0 npm: N/A Yarn: N/A pnpm: N/A Relevant Packages: next: 14.1.0 eslint-config-next: 14.1.0 react: 18.2.0 react-dom: 18.2.0 typescript: 5.3.3 ```

Describe the bug

Our use case requires writing cookies for all subdomains for a given domain (e.g. .domain.com). Amplify v6 does not appear to allow us to configure this the same way v5 did via the cookieStorage option. Amplify.configure() seems to offer a potential workaround by means of configuring a custom tokenProvider and credentialsProvider.

Please note that at this point in time, I am only trying to get this working client side since operations like signIn, signOut, etc are not supported in server actions as stated here.

However, after configuring these I receive the following error:

AuthUserPoolException: Auth UserPool not configured.
    at eval (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/core/dist/esm/errors/createAssertionFunction.mjs:14:19)
    at assertTokenProviderConfig (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/core/dist/esm/singleton/Auth/utils/index.mjs:23:69)
    at DefaultTokenStore.getAuthKeys (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenStore.mjs:129:101)
    at DefaultTokenStore.getDeviceMetadata (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenStore.mjs:109:37)
    at TokenOrchestrator.getDeviceMetadata (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenOrchestrator.mjs:132:37)
    at handlePasswordVerifierChallenge (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/utils/signInHelpers.mjs:500:52)
    at async retryOnResourceNotFoundException (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/utils/signInHelpers.mjs:796:16)
    at async signInWithSRP (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/apis/signInWithSRP.mjs:53:87)
    at async handleSignIn (webpack-internal:///(app-pages-browser)/./app/page.tsx:19:36)

Expected behavior

User can sign in using a custom token provider.

Reproduction steps

I've created a reproduction repo that showcases this issue. Please see reproduction steps outlined in the readme for "Issue 1" found in https://github.com/ryanwalters/amplify-6.

Code Snippet

No response

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

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 8 months ago

Hello, @ryanwalters and thanks for opening this issue. Greatly appreciate you creating a sample repo as well!

With the AuthUserPoolException error that you're experiencing, I believe that's being thrown because the code in your useAuth.ts file is going to be run server-side. If you're Next.JS but not wrapping the code in that file in a client scope, it's being evaluated on the server side.

Also, I see the scoped config for Auth in the sample app that you provided. Is that the same for your main app as well (not sure if they are the same repo/app)? Or are you using the auto-generated config from the CLI?

ryanwalters commented 8 months ago

With the AuthUserPoolException error that you're experiencing, I believe that's being thrown because the code in your useAuth.ts file is going to be run server-side. If you're Next.JS but not wrapping the code in that file in a client scope, it's being evaluated on the server side.

I've marked useAuth.ts with the 'use client' directive. This change has been pushed to the sample repo.

I now get a different error:

page.tsx:19 AuthUserPoolException: Auth UserPool not configured.
    at eval (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/core/dist/esm/errors/createAssertionFunction.mjs:14:19)
    at assertTokenProviderConfig (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/core/dist/esm/singleton/Auth/utils/index.mjs:23:69)
    at DefaultTokenStore.getAuthKeys (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenStore.mjs:129:101)
    at DefaultTokenStore.getDeviceMetadata (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenStore.mjs:109:37)
    at TokenOrchestrator.getDeviceMetadata (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/tokenProvider/TokenOrchestrator.mjs:132:37)
    at handlePasswordVerifierChallenge (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/utils/signInHelpers.mjs:500:52)
    at async retryOnResourceNotFoundException (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/utils/signInHelpers.mjs:796:16)
    at async signInWithSRP (webpack-internal:///(app-pages-browser)/./node_modules/@aws-amplify/auth/dist/esm/providers/cognito/apis/signInWithSRP.mjs:53:87)
    at async handleSignIn (webpack-internal:///(app-pages-browser)/./app/page.tsx:19:36)

Maybe this is progress? 😄

Also, I see the scoped config for Auth in the sample app that you provided. Is that the same for your main app as well (not sure if they are the same repo/app)? Or are you using the auto-generated config from the CLI?

Yes, we are using a pool that is created and configured in a separate application (as part of a larger CloudFormation stack rather than Amplify).

JoeyOverby commented 8 months ago

I'm having a similar issue where I get this error if I have a credentialsProvider in my configure call.

This works fine (but can't get custom creds of course....)

Amplify.configure(amplifyconfig);

But since I need some creds from Cognito and others from Auth0, when I do this it fails

const customCredentialsProvider = AuthApi.getCustomCredsProvider();
Amplify.configure(amplifyconfig, {
  Auth: {
    credentialsProvider: customCredentialsProvider,
  },
});

With the second set of code it fails on the non redirected/normal sign in call.

await signIn({
        username: email,
        password: "-",
      });

Error: "Auth UserPool not configured." Recovery Suggestion: "Make sure to call Amplify.configure in your app with userPoolId and userPoolClientId."

Clearly I have those there as the configure call without the credentialsProvider works fine. But by adding the credentials provider it fails to load until after the user has signed in. (Which they can't - because sign in fails...)

cwomack commented 8 months ago

@ryanwalters, can you detail how you're defining Amplify.configure() call as well as how you've set up your custom tokenProvider? Amplify.configure takes in 2 things, the resource config and then the library configs. As soon as you've done all the configuring, can you do the following to log out the config to see if anything unexpected is happening:

console.log(Amplify.getConfig)

CC: @JoeyOverby, can you do the same logging as well? Thanks!

ryanwalters commented 8 months ago

@cwomack The Amplify.configure() and token provider definitions can be found in the sample repo here: https://github.com/ryanwalters/amplify-6/blob/main/hooks/useAuth.ts#L12-L49

Let me know if you'd like me to paste them here instead.

The output of console.log(Amplify.getConfig()):

{
  Auth: {
    Cognito: {
      userPoolId: 'us-east-1_***',
      userPoolClientId: '***'
    }
  }
}
cwomack commented 6 months ago

@ryanwalters After looking again at the code example in your sample repo, you are configuring the tokenProvider and credentialsProvider for the server side use cases. However, other parts of your code are only using Amplify on the client side. Can you clarify if you’re calling any API’s on the server side?

If you are only intending to use Amplify on the client side, this document will show you how to configure the tokenProviders to change the cookie domain.

Let us know if this helps clear things up!

jeff2013 commented 5 months ago

I'm having a similar issue where I get this error if I have a credentialsProvider in my configure call.

This works fine (but can't get custom creds of course....)

Amplify.configure(amplifyconfig);

But since I need some creds from Cognito and others from Auth0, when I do this it fails

const customCredentialsProvider = AuthApi.getCustomCredsProvider();
Amplify.configure(amplifyconfig, {
  Auth: {
    credentialsProvider: customCredentialsProvider,
  },
});

With the second set of code it fails on the non redirected/normal sign in call.

await signIn({
        username: email,
        password: "-",
      });

Error: "Auth UserPool not configured." Recovery Suggestion: "Make sure to call Amplify.configure in your app with userPoolId and userPoolClientId."

Clearly I have those there as the configure call without the credentialsProvider works fine. But by adding the credentials provider it fails to load until after the user has signed in. (Which they can't - because sign in fails...)

I'm also seeing a similar issue. Login works until you add a customCredentials provider. When you add a customCredentialsProvider it throws the error: "Auth UserPool not configured".

cwomack commented 4 months ago

@jeff2013, can you open a separate issue that details what you're experiencing and any applicable reproduction steps? I haven't run into any issues using customCredentialsProvider, but if you can share some sample code that's causing resulting in this error and how you've set up the Authentication flows/imports then we can try to get you unblocked! Feel free to create a new issue here.

cwomack commented 4 months ago

@ryanwalters, I'll close this issue out for now since we haven't heard back. If you are still experiencing this, please feel free to reply back and provide any information previously requested (and review this comment) and we'd be happy to re-open the issue.

Thank you!

ryanwalters commented 3 months ago

@cwomack Apologies for the delayed response.

@ryanwalters After looking again at the code example in your sample repo, you are configuring the tokenProvider and credentialsProvider for the server side use cases. However, other parts of your code are only using Amplify on the client side. Can you clarify if you’re calling any API’s on the server side?

We need Amplify to work on both client and server (this is a Next.js application).

If you are only intending to use Amplify on the client side, this document will show you how to configure the tokenProviders to change the cookie domain.

Is there a reason tokenProviders could not work server side? I see that https://github.com/aws-amplify/amplify-js/issues/11598 has not had much activity since it was opened a year ago.

Ideally, we would have a way to configure a Cognito client that can perform all actions (e.g. sign in, sign out, token refresh, etc) on both the client and the server, including the ability to configure how and where cookies are written.

I would recommend taking a look at how Supabase handles this. They essentially provide functions for both the client and server that allow the end user to specify how to handle getting/setting/removing and configuring cookies.

Since we were not able to make Amplify 6 work for us, we ended up writing a very basic wrapper around @aws-sdk/client-cognito-identity-provider following a similar API as Supabase's to handle token and cookie management on the server (and middleware) while continuing to use Amplify 5 on the client side, but would obviously rather have an officially supported solution.

baalimago commented 2 months ago

Unfortunate that this ticket is closed. It's very much a problem. We have an angular app which we attempted to upgrade from amplify v5 -> v6. Configuration according to the getting started documentation which works just fine. But, the project uses federated social logins via identity pool (not user pool), which in turn requires federatedSignIn. Since federatedSignIn has been deprecated and replaced with CustomCredentialsProvider, we're sort of stuck.

In a nutshell, signIn does not work when the amplify configuration is this:

Amplify.configure(amplifyconfiguration, {
  Auth: {
    credentialsProvider: customCredentialsProvider
  }
});

It throws error error signing in AuthUserPoolException: Auth UserPool not configured.. In fact, this very minimal change is enough to break signIn:

Amplify.configure(amplifyconfiguration, {
  Auth: {}
});

But changing it to this, makes signin work once more (like it did on v5):

Amplify.configure(amplifyconfiguration);

So basically ,whenever we try to configure Amplify using any LibraryOptions, the user can't sign in. What's odd is that it works prefectly fine to sign up (with verification code) + reset password, only signin doesn't work.

Since we can't change the federation from identity pool -> user pool without a massive migration headache (a 'migrane', perhaps, if I may be so punny), I fear we'll be stuck using amplify v5 until this has been resolved.