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

Add support for idp_identifier query parameter when going through OAuth #10226

Open
1 of 2 tasks
jaredready opened this issue Aug 18, 2022 · 3 comments · May be fixed by #10505
Open
1 of 2 tasks

Add support for idp_identifier query parameter when going through OAuth #10226

jaredready opened this issue Aug 18, 2022 · 3 comments · May be fixed by #10505
Labels
Auth Related to Auth components/category Cognito Related to cognito issues feature-request Request a new feature Service Team Issues asked to the Service Team

Comments

@jaredready
Copy link

Is this related to a new or existing framework?

React

Is this related to a new or existing API?

Authentication

Is this related to another service?

No response

Describe the feature you'd like to request

Cognito User Pools federated identities supports using identifiers (typically a domain name) to correctly figure out what IdP a user should be authenticating with based on their email address. This is described in the Cognito documentation here.

You can also choose identifiers for your SAML providers. An identifier uniquely resolves to an identity provider (IdP) associated with your user pool. Typically, each identifier corresponds to an organization domain that the SAML IdP represents. For a multi-tenant app that multiple organizations share, you can use identifiers to redirect users to the correct IdP. Because the same organization can own multiple domains, you can provide multiple identifiers. To sign in your users with an identifier, direct their sessions to the Authorize endpoint for your app client with an idp_identifier parameter.

Following the link, you can see that the /oauth2/authorize endpoint supports an optional idp_identifier query parameter for providing this information.

I would like to be able to use the Auth.federatedSignIn function to be able to utilize this functionality.

Currently Amplify applications utilizing multiple identify providers need to jump through some awkward hoops to get their authentication code working correctly, but Cognito already supports the required functionality.

Describe the solution you'd like

Currently the Auth package provides a federatedSignIn function that has a required provider. I would like to see this function's input type enhanced to something like the following.

export declare type FederatedSignInOptions = {
    provider?: CognitoHostedUIIdentityProvider;
    idpIdentifier?: string;
    customState?: string;
};

Maybe something a little smarter to require either provider or idpIdentifier; my TypeScript isn't that good.

This would allow one to do something like,

Auth.federatedSignIn({ idpIdentifier: "example.com" });

and have the user be directed to their correct IdP to authenticate.

Describe alternatives you've considered

I've tried to see if it would be possible to abuse the current behavior to make this work, but you can see here that there's currently no way to provide additional query parameters to make this request work.

Additional context

The documentation here has a handy graphical overview of the workflow.

Is this something that you'd be interested in working on?

  • 👋 I may be able to implement this feature request
  • ⚠️ This feature might incur a breaking change
@jaredready jaredready added the feature-request Request a new feature label Aug 18, 2022
@siman4457
Copy link

siman4457 commented Aug 20, 2022

I was looking to add exactly this to my Amplify application since I have a multi-tenant app that multiple organizations share. I'd like to see this added to the federatedSignIn function as well.

The current workaround I'm envisioning for this is to create a mapping between the identifier (ex: company.com) and the provider name in a DB.

@abdallahshaban557 abdallahshaban557 added the Auth Related to Auth components/category label Aug 22, 2022
@ncarvajalc
Copy link
Contributor

ncarvajalc commented Oct 18, 2022

Context

Even though there is no official documentation for this feature, it is possible without major workarounds. I am currently implementing federated sign in using AzureAD as my third party provider using OpenID (It is also possible using SAML).

Notice that the provider argument is the identity_provider query parameter that you mentioned in the Authorize endpoint API, so there is no need to create new arguments.

const queryString = Object.entries({
			redirect_uri: redirectSignIn,
			response_type: responseType,
			client_id: clientId,
			identity_provider: provider, // This is already implemented in
			                                Amplify
			scope: scopesString,
			state,
			...(responseType === 'code' ? { code_challenge } : {}),
			...(responseType === 'code' ? { code_challenge_method } : {}),
		})
			.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
			.join('&');

		const URL = `https://${domain}/oauth2/authorize?${queryString}`;
		logger.debug(`Redirecting to ${URL}`);
		this._urlOpener(URL, redirectSignIn);

Reproduction steps

CLI

First you need to amplify add auth and select Apply default configuration with Social Provider (Federation). You will be asked for a domain name prefix. You should supply the following information:

  • Sign in URI(s)
  • Sign out URI(s)

When being prompted for the identity providers you want to configure for your user pool press enter without selecting any. This will create a user pool and create a Cognito domain that you will need in your third party auth provider.

amplify push to see your changes in the cloud.

AWS Console

Head to the AWS Console and search for AWS Amplify. Select all apps and click the app you are using. There you can select the Authentication category you just created:
Pasted image 20221018124809
Once there, select the View in Cognito option:
Pasted image 20221018124658
That will open your Amazon Cognito console. Select Sign-in experience and click in Add identity provider:
Pasted image 20221018125012
You can select the third party identifier you are going to use. Be sure to use a provider name you will remember, this will be used as the provider argument in your Auth.federatedSignIn function:
Pasted image 20221018125513
Fill in the rest of the information and click in Add identity provider.

After that the identity provider you just created should show up. You should go into App integration and scroll down to the App client list. Select the app that ends in clientWeb (You can follow the same procedure for the app_client app if needed):
Pasted image 20221018130332
From there go to Hosted UI and tap the Edit button:
Pasted image 20221018130526
Scroll down to Identity providers and select the one you just created and hit Save changes at the end of the page:
Captura de Pantalla 2022-10-18 a la(s) 1 06 56 p m

Third party provider

You should configure your third party provider using the following documentation for SAML and this documentation for OIDC. The redirect URI is key for the flow to work correctly.

Front end

You can use the following React code to test your newly created IdP. Notice that the provider is a string containing the name of the newly created IdP:

import { Auth } from "aws-amplify";
import { useEffect, useState } from "react";

export default function SignInPage() {
  const [user, setUser] = useState(null);

  const signIn = async () => {
    try {
      await Auth.federatedSignIn({ provider: "Azure" });
    } catch (error) {
      console.log("error signing in", error);
    }
  };

  useEffect(() => {
    getUser().then((userData) => setUser(userData));
  }, []);

  function getUser() {
    return Auth.currentAuthenticatedUser()
      .then((userData) => userData)
      .catch(() => console.log("Not signed in"));
  }

  return (
    <div>
      <h1>
        Welcome{" "}
        {user
          ? JSON.stringify(user.attributes.email)
          : "Ups! Not signed in"}
      </h1>
      {user ? (
        <button onClick={() => Auth.signOut()}>Sign Out</button>
      ) : (
        <button onClick={signIn}>Federated Sign In</button>
      )}
    </div>
  );
}

Once you click the button you should be redirected to your IdP and a new user should be created in your Cognito user pool.

Edit: Just realized you were asking about another query parameter. I'll leave the comment as a tutorial for adding third party idps.

@igorlg
Copy link

igorlg commented Aug 4, 2023

Just to add to this discussion, I faced exactly the same issue described by @ncarvajalc (thanks for the great walkthrough, BTW) and managed to do the UserPool IdP setup from within Amplify using overrides:

  1. (Assuming you already have auth setup in the project) generate a overrides file for Auth:
amplify override auth

This will create a file under amplify/backend/auth/override.ts (details in the docs here).

  1. Use this file to create a CloudFormation resource of type AWS::Cognito::UserPoolIdentityProvider (details here) with your IdP details:
import { AmplifyAuthCognitoStackTemplate, AmplifyProjectInfo } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyAuthCognitoStackTemplate, amplifyProjectInfo: AmplifyProjectInfo) {
    resources.addCfnResource(
        {
          type: "AWS::Cognito::UserPoolIdentityProvider",
          properties: {
            AttributeMapping: {
              <your K:V attribute mappings>
            },
            ProviderDetails: {
              client_id: "<your client id>",
              client_secret: "<your client secret>",
              authorize_scopes: "openid",
              oidc_issuer: "<oidc issuer URL>",
              attributes_url_add_attributes: false,
              attributes_request_method: "GET"
            },
            ProviderName: "<your provider name>",
            ProviderType: "OIDC",
            UserPoolId: {
              Ref: "UserPool",
            },
          },
        },
        "oidc-provider"
    );
}
  1. Push changes to Amplify
amplify push

After this point, it is possible to call Auth.federatedSignIn() in your app to redirect the user to the OIDC provider. You do need to specify the provider name - the same used in the CfnResource above - like so:

Auth.federatedSignIn({ provider: "<your provider name>" } as any);

Hope this helps!

@nadetastic nadetastic self-assigned this Aug 4, 2023
@cwomack cwomack added the need-product-input Needs non-technical requirements or direction to proceed label Sep 3, 2024
@cwomack cwomack added Service Team Issues asked to the Service Team Cognito Related to cognito issues and removed need-product-input Needs non-technical requirements or direction to proceed labels Sep 30, 2024
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 Cognito Related to cognito issues feature-request Request a new feature Service Team Issues asked to the Service Team
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants