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.42k stars 2.12k forks source link

Authorization Code not consumed to sign in user #13503

Closed TimTimT closed 2 months ago

TimTimT commented 3 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 ```

Describe the bug

After my user signs in using SSO, they are redirected to my application with an authorization code as the parameter "code" in the URI parameters. At this point, the code should be exchanged for tokens, and the user should be signed in.

At least, this was what happened in amplify V4, which I just migrated from. It seems that either, this default behaviour of listening to the "code" parameter no longer works, or I need to handle the code differently in V6.

I do not use signInWithRedirect because I do not want to use the UI. Instead, I redirect the user to: https://${HOSTED_UI_DOMAIN}.auth.eu-central-1.amazoncognito.com/oauth2/authorize?idp_identifier=${idp_identifier}&redirect_uri=${REDIRECT_URI}/auth/login&response_type=CODE&client_id=${CLIENT_ID}&scope=email%20openid%20profile

Expected behavior

Authorization code is consumed, exchanged for tokens, and the user is signed in.

I am aware that automatic consumption of all queryparameters with key "code" was an issue in prior versions of amplify, because I have run into it myself. But if this has been resolved, I am not sure what, if anything, replaced the automatic consumption mechanism.

Reproduction steps

  1. Sign in user via SSO bypassing the hosted UI.
  2. Receive code response

Code Snippet

// Put your code below this line.

Log output

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

aws-exports.js

No response

Manual configuration

{
  "aws_project_region": "eu-central-1",

  "aws_cognito_identity_pool_id": "eu-central-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",

  "aws_cognito_region": "eu-central-1",

  "aws_user_pools_id": "eu-central-1_xxxxxxxxx",

  "aws_user_pools_web_client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",

  "oauth": {
    "domain": "example.auth.eu-central-1.amazoncognito.com",

    "scope": ["email", "openid", "profile"],

    "redirectSignIn": "https://example.com/auth/login",

    "redirectSignOut": "https://example.com/auth/sign-out",

    "responseType": "code"
  },

  "federationTarget": "COGNITO_USER_POOLS",

  "aws_cognito_username_attributes": ["EMAIL"],

  "aws_cognito_social_providers": [],

  "aws_cognito_signup_attributes": [],

  "aws_cognito_mfa_configuration": "OFF",

  "aws_cognito_mfa_types": [],

  "aws_cognito_password_protection_settings": {
    "passwordPolicyMinLength": 8,

    "passwordPolicyCharacters": [
      "REQUIRES_LOWERCASE",

      "REQUIRES_UPPERCASE",

      "REQUIRES_NUMBERS",

      "REQUIRES_SYMBOLS"
    ]
  },

  "aws_cognito_verification_mechanisms": [],
  "aws_app_id": "xxxxxxxxxxxxxx"
}

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

israx commented 3 months ago

Hello @TimTimT. Thanks for bringing this up. The signInWithRedirect API calls the same endpoint under the hood. You can bypass the Hosted UI view by providing the name of your IdP, e.g. signInWithRedirect({custom:'custom-prov'}).

Will that be enough for your use case? Or are you initiating the sign-in flow from a different app and then redirecting to another?

TimTimT commented 3 months ago

Hi @israx , Thank you for your feedback! I tried this out, and I get redirected to the hosted UI.

I suspect it might not work as expected due to there being a difference between the idp_identifier and the idp name. If I understand correctly, the signInWithRedirect function accepts a 'custom' field, which should receive the name of the identity provider to apply. In contrast, the _idpidentifier parameter in the URL takes one of the "identifiers" of the identity provider, which is a list of keys that helps us identify which identity provider should be selected.

In our case, the identifiers are the domain names of our clients, which use various identity providers to log into our application.

We are not redirecting to another application, the user gets redirected back to the original single-page application.

Is there another way to get amplify to listen to "code" parameters, or to force the redirect to occur with the specific idp_identifier?

israx commented 3 months ago

Hello @TimTimT. Thank you for providing context. Amplify v6 doesn't expose a listener to complete OAuth flows. In your case, Amplify needs to support the idp_identifier parameter and allow the signInWithRedirect API to pass it.

TimTimT commented 3 months ago

Hi @israx , that would work for me. For now, is it possible for me to directly call the function(s) that the amplify listener would otherwise call when an authorization code is detected? It would be excellent if I could listen for the code myself, and subsequently call the relevant amplify function manually.

israx commented 3 months ago

Unfortunately, we currently do not expose the listener. However, this feature request is being tracked by other GitHub issue (#13343). If you would like, you can give it a thumbs up to help increase traction for this feature.

ashwinkumar6 commented 2 months ago

Hi @TimTimT

we'll consolidate this into the above referenced https://github.com/aws-amplify/amplify-js/issues/13343 as a duplicate issue. The feature request to bring that functionality back in v6 is captured there, so feel free to add any additional upvotes, comments, context, etc. on that issue. Thank you!