Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support completing an OAuth flow that is not initiated by Amplify (signInWithRedirect) #13343

Open
3 tasks done
bbdev9805 opened this issue May 7, 2024 · 32 comments
Open
3 tasks done
Labels
Auth Related to Auth components/category feature-request Request a new feature VP Version parity issues between v5 and v6

Comments

@bbdev9805
Copy link

Before opening, please confirm:

JavaScript Framework

Angular

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

auth

Backend

Amplify CLI

Environment information

# Put output below this line

  System:
    OS: macOS 14.1
    CPU: (12) arm64 Apple M3 Pro
    Memory: 66.95 MB / 18.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 16.20.0 - /usr/local/bin/node
    npm: 8.19.4 - /usr/local/bin/npm
  Browsers:
    Chrome: 124.0.6367.119
    Safari: 17.1
  npmPackages:
    aws-amplify: ^6.0.28 => 6.0.28 
  npmGlobalPackages:
    @angular/cli: 16.2.0
    @aws-amplify/cli: 12.10.1
    corepack: 0.17.0
    npm: 8.19.4


Describe the bug

SSO via SAML works for SP-initiated but not for IdP-initiated SSO after upgrading to v6 from v5. I am redirected from the Idp to [https://www.example.com/?code=Authorization code] but cannot obtain the authentication token. When the getCurrentUser API is executed, a UserUnAuthenticatedException error occurs. IdP-initiated SSO also works in V5. This needs to be resolved immediately if IdP-initiated SSO is to be supported. https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-SAML-session-initiation-idp-initiation.html

Expected behavior

As in V5, the token can be obtained correctly after redirecting from the Idp.

Reproduction steps

  1. Access Idp's portal page.
  2. Select the displayed application.
  3. Redirect to https://www.example.com?code=[Authorization code].
  4. UserUnAuthenticatedException error occurs by getCurrentUser() .

Code Snippet

// Put your code below this line.

// Execute `getCurrentUser()` after being redirected from Idp.
await Auth.getCurrentUser();

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

@bbdev9805 bbdev9805 added the pending-triage Issue is pending triage label May 7, 2024
@israx
Copy link
Member

israx commented May 7, 2024

hello @bbdev9805 . Sorry for any inconvenience using the library. Amplify v6 supports OAuth flows initiated from the same App only. You would need to kick off the OAuth flow by calling the signInWithRedirect API

@cwomack cwomack added the Auth Related to Auth components/category label May 7, 2024
@cwomack cwomack self-assigned this May 7, 2024
@cwomack cwomack added question General question pending-response and removed pending-triage Issue is pending triage labels May 7, 2024
@bbdev9805
Copy link
Author

@israx
I have confirmed that it works with the signInWithRedirect API. However, when using IdP-initiated SSO, redirection occurs, making it impossible to use the signInWithRedirect API. What does it mean that IdP-initiated SSO, which was recently supported, cannot be used with Amplify v6? https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-SAML-session-initiation-idp-initiation.html

@israx
Copy link
Member

israx commented May 8, 2024

supporting IdP logins would be a feature request. The Auth singleton in Amplify v5 has a listener that would capture any code query param returned from the social provider and finish the authentication process. Ideally we would need to have a dedicated API that allows to do the same.

@israx israx added feature-request Request a new feature and removed question General question labels May 8, 2024
@cwomack cwomack changed the title SSO via SAML works for SP-initiated but not for IdP-initiated SSO after upgrading to v6 from v5 Support completing an OAuth flow that is not initiated by Amplify (signInWithRedirect) May 9, 2024
@Pylinho
Copy link

Pylinho commented Jun 19, 2024

@israx have you got any further with the request to fix/begin supporting IdP logins again in v6? I am relying on this to upgrade from Amplify v5 -> v6.

Cheers.

@chapati
Copy link

chapati commented Jun 27, 2024

+1 for support please

@hakonmuggerud
Copy link

+1 as well. We are depending on this featured to be able to upgrade to version 6

@TimTimT
Copy link

TimTimT commented Jun 30, 2024

+1 Same

@Maxiweb
Copy link

Maxiweb commented Jul 8, 2024

+1 Cant update to v6 without this

@cwomack cwomack removed their assignment Jul 8, 2024
@cwomack cwomack added the VP Version parity issues between v5 and v6 label Jul 8, 2024
@OmarMuhtaseb
Copy link

+1

@OmarMuhtaseb
Copy link

FYI,
There was a duplicate issue, and it was suggested to downgrade to v5

#12983 (comment)

@israx
Copy link
Member

israx commented Jul 17, 2024

Hello everyone. I'll revisit this issue with the team to discuss its prioritization. Thank you for your patience.

@jhw
Copy link

jhw commented Jul 19, 2024

I deleted my comment because I think in retrospect it wasn't related to this specify issue - it seems I had in fact failed to configure my S3 bucket properly for SPA hosting - so apologies for that

@pedrokiefer
Copy link

+1

@tllatruw
Copy link

Hi @israx , Is there any news on this? I suppose the conclusion was that this is not a priority?

@hakonmuggerud
Copy link

Any news on this issue? We are blocked from upgrading to version 6 because of this.

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Jan 16, 2025
@HuiSF
Copy link
Member

HuiSF commented Jan 16, 2025

Hey @hakonmuggerud We are currently evaluating this use case while considering maintaining the OAuth 2.0 specs required security posture. Thanks for your patience.

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Jan 16, 2025
@josefaidt
Copy link
Contributor

Hey folks in the thread 👋 in an effort to better understand the use cases for sign-in events initiated from an upstream, OAuth-based identity provider, I have a few questions:

  • are the identity providers OIDC compliant? would you be open to disclosing the provider name?
  • are the sign-in events initiated from an "app portal" of sorts where you are seeking to share user sessions with individual apps in your organization?
  • how are you currently handling such sign-in events in your application code?

@paulcwatts
Copy link

I just ran into this as well trying to add IdP-initiated SAML authentication for my amplify v6 app. To answer your questions:

  1. Yes, I am using an OIDC compliant IdP (Microsoft Entra). I am able to complete the flow using non-Amplify apps.
  2. Yes, from the Microsoft 365 App Portal
  3. I'm currently not, I was adding support for IdP-initiated SAML when I found out that Cognito would support it. I currently use only SP-initiated SAML.

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 4, 2025
@cwomack
Copy link
Member

cwomack commented Feb 4, 2025

Thanks for following up with the answers to @josefaidt's questions, @paulcwatts. Anyone else following this issue, feel free to do the same! While there's no update yet, we are taking note of these use cases to better understand how to support this feature.

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 4, 2025
@paulcwatts
Copy link

For what it's worth, I have an interesting workaround: if my callback is called with a code query parameter but not a state parameter, I just call signInWithRedirect to initiate an SP-initiated flow. That redirects to Cognito's managed login domain, which, since it was previously authenticated via the IdP-initiated flow, directly redirects back to my app with both a code and state parameter. Those allow the OAuth listener to complete the authentication flow.

Basically:

  1. GET <Launch URL> (launch my app via myapps.microsoft.com)
  2. GET https://login.microsoft.com/xxxxx/saml2?SAMLRequest=yyy (SAML Request)
  3. POST https://<cognito managed domain>/saml2/idpresponse (SAML Response)
  4. GET https://<myapp callback>?code=xxxx
  5. GET https://<<cognito managed domain</oauth2/authorize? (result of calling signInWithRedirect)
  6. GET https://<myapp callback>?code=yyyy&state=zzzz

Maybe this will work for others in this situation.

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 4, 2025
@josefaidt
Copy link
Contributor

Hey @paulcwatts are you looking to set up Microsoft Entra ID as a SAML provider or OIDC? If SAML you should be okay directing the request to Cognito, who will then redirect to your app

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 5, 2025
@paulcwatts
Copy link

@josefaidt I'm setting it up as a SAML provider, using these instructions: https://aws.amazon.com/blogs/security/how-to-set-up-saml-federation-in-amazon-cognito-using-idp-initiated-single-sign-on-request-signing-and-encrypted-assertions/

That's correct, when I configure Entra it goes to Cognito first, then goes to my callback URL (specified in the RelayState). However, the callback is only given a code parameter, not a state parameter. The OAuth listener will only complete the authentication process if it finds both a code and state parameter. So while the user is logged in on the Cognito managed page, they aren't ever logged in to my app.

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 5, 2025
@josefaidt
Copy link
Contributor

Hey @paulcwatts thanks for adding those details! Looking into this a bit further you will need to set up your app portal (or rather the page where you're initiating the upstream sign-in) to direct to your app first. Cognito can not be used as a SAML provider, but following the route of initiating sign-in from your app will allow your end users to connect to the same session as Cognito is orchestrating sign-in:

  1. starting from your enterprise app portal, or some page, navigate to your app
  2. from your app, either check for an active session and redirect, or immediately redirect given some query parameter to Cognito
  3. passing the provider to signInWithRedirect will navigate to your SAML provider
  4. end user should connect to their existing session
  5. SAML provider redirects to Cognito which redirects back to your app with Cognito-vended tokens

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 5, 2025
@bhelabhav
Copy link

bhelabhav commented Feb 5, 2025

Hey @josefaidt or @paulcwatts. I don't even see this working with SP-initiated flow. Maybe same root cause or different - not clear. Appreciate any help

Specs

  • v6
  • react
  • auth
  • gen 2 backend

Source Doc
https://docs.amplify.aws/react/build-a-backend/auth/examples/microsoft-entra-id-saml/
^ also @josefaidt - appears you were the sole contributor for this page so hoping to get clarity here. I just followed these instructions for setup and got stuck at this problem.

The Problem

After calling signInWithRedirect and authenticating with the SAML provider, the callback page does not consume the code and state query parameters.

#13343 (comment)

@josefaidt I'm setting it up as a SAML provider, using these instructions: https://aws.amazon.com/blogs/security/how-to-set-up-saml-federation-in-amazon-cognito-using-idp-initiated-single-sign-on-request-signing-and-encrypted-assertions/

That's correct, when I configure Entra it goes to Cognito first, then goes to my callback URL (specified in the RelayState). However, the callback is only given a code parameter, not a state parameter. The OAuth listener will only complete the authentication process if it finds both a code and state parameter. So while the user is logged in on the Cognito managed page, they aren't ever logged in to my app.

^ I do see both code and state (again, SP-initiated flow), but the app using the Authenticator UI component doesn't seem to do anything with it.

#13343 (comment)

supporting IdP logins would be a feature request. The Auth singleton in Amplify v5 has a listener that would capture any code query param returned from the social provider and finish the authentication process. Ideally we would need to have a dedicated API that allows to do the same.

The Auth singleton in Amplify v5 has a listener that would capture any code query param returned from the social provider and finish the authentication process

Is the Authenticator component fumbling SP-initiated flow here? According to the Source Doc and given that the amplify gen 2 docs point to using the Authenticator component for setting up auth, it seems like this should just otherwise work. When you wrote the documentation @josefaidt what was your setup?

The Flow

User ...

  1. Navigates to /app (wrapped in Authenticator component)
  2. Click's Login with SAML -> signInWithRedirect redirects to SAML Provider
  3. Login at SAML Provider
  4. Is redirected to callback url /app?code=someToken&state=someState
  5. Problem: The app does not do anything with the searchparams

Code
/app

Amplify.configure(outputs, { ssr: true })

export default function AppLayout({ children }: { children: ReactNode }) {
  return (
    <Authenticator
      components={components}
      hideSignUp
      variation="default"
    >
      <EnsureSessionRefresh />
      <AuthEventHandlers />
      {children}
    </Authenticator>
  )
}

const components = {
  SignIn: {
    Header() {
      return (
        <>
          <div className="flex flex-col items-center justify-center px-8 pt-8">
            <h2 className="text-center text-2xl font-semibold">
              Corporate Sign-In
            </h2>
            <SAMLLoginForm />
          </div>
          <div className="flex flex-col items-center">
            <hr className="my-8 w-5/6" />
          </div>
          <h2 className="text-center text-2xl font-semibold">Sign-In</h2>
        </>
      )
    }
  }
}

// SOURCE: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-managing-saml-idp-naming.html
// SOURCE: https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html
// SOURCE: https://docs.amplify.aws/react/build-a-backend/auth/examples/microsoft-entra-id-saml/
function SAMLLoginForm() {
  const [orgId, setOrgId] = React.useState<string>('')
  const placeholder = ''

  const submitHandler = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    if (!orgId) {
      // NOTE: This can only happen if there is a bug
      //       in our code.
      alert(placeholder)
    } else {
      signInWithRedirect({ provider: { custom: orgId } })
    }
  }

  return (
    <form className="flex w-full flex-col gap-y-4" onSubmit={submitHandler}>
      <div className="space-y-2">
        <label className="amplify-label" htmlFor="corporate-email">
          Email
        </label>
        <input
          id="corporate-email"
          onChange={(e) => {
            const orgId = e.target.value.split('@')[1]
            setOrgId(orgId)
          }}
          type="email"
          placeholder={placeholder}
          className="amplify-input"
        />
      </div>
      <button
        type="submit"
        className={cn(
          'amplify-button amplify-button--primary w-full',
          !orgId && 'cursor-not-allowed bg-gray-400',
        )}
      >
        Sign in
      </button>
    </form>
  )
}

Other Issues
Looked at these:
#12983 (which points to this thread)

aws-amplify/amplify-ui#6306
aws-amplify/amplify-ui#1152
^ seem tangentially related, but red herring issues as it relates to the problem seen. LMK if mistaken

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 5, 2025
@paulcwatts
Copy link

It seems like this is getting a bit off the rails, so I want to be clear with the facts as I know them:

  1. I am trying to support IdP-initiated SAML in my Amplify app.
  2. IdP-initiated SAML is defined as when the Cognito user pool receives a unsolicited SAML response from the external identity provider (in my case, Entra).
  3. If my app is the one starting the flow (via signInWithRedirect), it is by definition not an IdP-initiated flow, it's an SP-initiated flow. SP-initiated flows work for me just fine.
  4. Cognito user pools definitely support IdP-initiated SAML flows: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-SAML-session-initiation.html. I'm able to implement it in a non-Amplify app.

To answer your question, @josefaidt , as far as I am aware I cannot set Entra's app portal to direct to my app first. The app link that it creates looks like https://launcher.myapps.microsoft.com/api/signin/xxxx?tenantId=yyy, which starts the IdP-initiated SAML flow.

In any event, like I said, if I were to redirect to my app first and then use signInWithRedirect, that is by definition not IdP-initiated SAML.

So what I'm really just asking is that Amplify support what Cognito supports -- which is IdP-initiated SAML -- by finishing the flow (calling the OAuth /token/ endpoint) where there is only a code parameter.

@paulcwatts
Copy link

paulcwatts commented Feb 5, 2025

As far as I can tell, this is the initial source of the issue: https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/providers/cognito/utils/oauth/completeOAuthFlow.ts#L89

Notice how it doesn't complete the flow if there's no state query parameter. Because in IdP-initiated SAML, the app does not initiate the SAML flow, there's no way for the IdP to provide it that state parameter, at least not in the form that Amplify is looking for.

The bigger problem is that the rest of the code depends on that state parameter being there. I've only looked into this cursorily, so I don't know how much depends on it.

@HuiSF
Copy link
Member

HuiSF commented Feb 5, 2025

Hey @bhelabhav thank you for reporting the issue with great details.

Reading the issue description, I suspect that the cause is that the OAuth completion listener was not attached and executed within the JS bundle of the callback URL in your app.

The OAuth listener is a side effect that resides along with the signInWithRedirect API. If the API is not bundled, then the side effect won't be executed. Could you confirm whether the callback URL in your app actually bundles the signInWithRedirect API? If not, and you can't include the signInWithRedirect API for any reason, you can import the following module to the bundle used by the callback URL to ensure the OAuth listener is attached so it can complete the OAuth flow:

import 'aws-amplify/auth/enable-oauth-listener';

See this doc for more details.

To be noted, your issue is not related to the OP's request, as your OAuth flow is initiated with the signInWithRedirect() API within your app.

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 5, 2025
@bhelabhav
Copy link

Hey @bhelabhav thank you for reporting the issue with great details.

Reading the issue description, I suspect that the cause is that the OAuth completion listener was not attached and executed within the JS bundle of the callback URL in your app.

The OAuth listener is a side effect that resides along with the signInWithRedirect API. If the API is not bundled, then the side effect won't be executed. Could you confirm whether the callback URL in your app actually bundles the signInWithRedirect API? If not, and you can't include the signInWithRedirect API for any reason, you can import the following module to the bundle used by the callback URL to ensure the OAuth listener is attached so it can complete the OAuth flow:

import 'aws-amplify/auth/enable-oauth-listener';
See this doc for more details.

To be noted, your issue is not related to the OP's request, as your OAuth flow is initiated with the signInWithRedirect() API within your app.

Got it - thanks for clarifying. Let me fork a new issue from this one.

@willbonde
Copy link

import 'aws-amplify/auth/enable-oauth-listener';

Hey @bhelabhav thank you for reporting the issue with great details.

Reading the issue description, I suspect that the cause is that the OAuth completion listener was not attached and executed within the JS bundle of the callback URL in your app.

The OAuth listener is a side effect that resides along with the signInWithRedirect API. If the API is not bundled, then the side effect won't be executed. Could you confirm whether the callback URL in your app actually bundles the signInWithRedirect API? If not, and you can't include the signInWithRedirect API for any reason, you can import the following module to the bundle used by the callback URL to ensure the OAuth listener is attached so it can complete the OAuth flow:

import 'aws-amplify/auth/enable-oauth-listener';
See this doc for more details.

To be noted, your issue is not related to the OP's request, as your OAuth flow is initiated with the signInWithRedirect() API within your app.

I can confirm the import in the comment resolved our issue with authentication not completing for OAuth logins

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 24, 2025
@jjarvisp jjarvisp removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auth Related to Auth components/category feature-request Request a new feature VP Version parity issues between v5 and v6
Projects
None yet
Development

No branches or pull requests