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 example for Entra ID with SAML #7732

Merged
merged 13 commits into from
Oct 18, 2024
Merged
josefaidt marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/directory/directory.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ export const directory = {
{
path: 'src/pages/[platform]/build-a-backend/auth/data-usage-policy/index.mdx'
},
{
path: 'src/pages/[platform]/build-a-backend/auth/examples/index.mdx',
children: [
{
path: 'src/pages/[platform]/build-a-backend/auth/examples/microsoft-entra-id-saml/index.mdx'
}
]
},
{
path: 'src/pages/[platform]/build-a-backend/auth/grant-access-to-auth-resources/index.mdx'
},
Expand Down
36 changes: 36 additions & 0 deletions src/pages/[platform]/build-a-backend/auth/examples/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getChildPageNodes } from '@/utils/getChildPageNodes';
import { getCustomStaticPath } from '@/utils/getCustomStaticPath';

export const meta = {
title: 'Examples',
description:
'Learn how to address different business use cases with Amplify Auth',
route: '/[platform]/build-a-backend/auth/examples',
platforms: [
'android',
'angular',
'flutter',
'javascript',
'nextjs',
'react',
'react-native',
'swift',
'vue'
]
};

export function getStaticPaths() {
return getCustomStaticPath(meta.platforms);
}

export function getStaticProps() {
const childPageNodes = getChildPageNodes(meta.route);
return {
props: {
meta,
childPageNodes
}
};
}

<Overview childPageNodes={props.childPageNodes} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
import { getCustomStaticPath } from '@/utils/getCustomStaticPath';

export const meta = {
title: 'Microsoft Entra ID (SAML)',
description: 'Learn how to connect a Microsoft Entra ID provider with SAML',
platforms: [
'android',
'angular',
'flutter',
'javascript',
'nextjs',
'react',
'react-native',
'swift',
'vue'
]
};

export function getStaticPaths() {
return getCustomStaticPath(meta.platforms);
}

export function getStaticProps() {
return {
props: {
meta,
}
};
}

Microsoft Entra ID can be configured as a SAML provider for use with Amazon Cognito. Integrating Entra ID enables you to sign in with your existing enterprise users, and maintain profiles unique to the Amplify Auth resource for use within your Amplify app. To learn more, visit the [Azure documentation for SAML authentication with Microsoft Entra ID](https://learn.microsoft.com/en-us/entra/architecture/auth-saml).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if i'm using some other SAML provider? Are there generic docs I can follow or lean on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have this page which is sort of generic, should we link out in case someone lands on this page but is looking for general guidance? https://docs.amplify.aws/react/build-a-backend/auth/concepts/external-identity-providers/#configure-saml-provider


## Start your personal cloud sandbox

To get started, define your Amplify Auth resource with the appropriate redirect URIs:

```ts title="amplify/auth/resource.ts"
import { defineAuth } from "@aws-amplify/backend"

/**
* Define and configure your auth resource
* @see https://docs.amplify.aws/gen2/build-a-backend/auth
*/
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
logoutUrls: ["http://localhost:3000/come-back-soon"],
callbackUrls: ["http://localhost:3000/profile"],
},
},
})
```

Deploy to your personal cloud sandbox with `npx ampx sandbox`. This will generate a domain you can use to configure your new Entra ID App. After deploying your changes successfully, copy the generated `domain` value from `amplify_outputs.json`

```json title="amplify_outputs.json"
{
"auth": {
"aws_region": "us-east-1",
"user_pool_id": "<your-cognito-user-pool-id>",
"user_pool_client_id": "<your-cognito-user-pool-client-id>",
"identity_pool_id": "<your-cognito-identity-pool-id>",
"mfa_methods": [],
"standard_required_attributes": [
"email"
],
"username_attributes": [
"email"
],
"user_verification_types": [
"email"
],
"mfa_configuration": "OFF",
"password_policy": {
"min_length": 8,
"require_numbers": true,
"require_lowercase": true,
"require_uppercase": true,
"require_symbols": true
},
"oauth": {
"identity_providers": [],
"redirect_sign_in_uri": [
"http://localhost:3000/profile"
],
"redirect_sign_out_uri": [
"http://localhost:3000/come-back-soon"
],
"response_type": "code",
"scopes": [
"phone",
"email",
"openid",
"profile",
"aws.cognito.signin.user.admin"
],
// highlight-next-line
"domain": "<some-hash>.auth.us-east-1.amazoncognito.com"
},
},
"version": "1"
}
```

## Set up Microsoft Entra ID

Next, navigate to [portal.amazon.com](https://portal.azure.com/), select **Entra ID**. In your default directory, or company's existing directory, under **Manage**, select **Enterprise Applications**

![Entra ID default directory page highlighting Enterprise Applications](/images/auth/examples/microsoft-entra-id-saml/entra-id-select-enterprise-applications.png)

Afterwards, select **New application**, then select **Create your own application**. Specify a name for the application and choose **Integrate any other application you don't find in the gallery (Non-gallery)**

![Azure portal creating a new enterprise application for Entra ID](/images/auth/examples/microsoft-entra-id-saml/entra-id-new-enterprise-application.png)

Now that you have created the new enterprise application you can begin to configure Single Sign-on with SAML. Select **Single sign-on**

![Entra ID enterprise application highlighting "single sign-on"](/images/auth/examples/microsoft-entra-id-saml/entra-id-select-single-sign-on.png)

Then select **SAML**

![Entra ID enterprise application single sign-on setup highlighting "SAML"](/images/auth/examples/microsoft-entra-id-saml/entra-id-select-saml.png)

You will be directed to a page to set up single sign-on with SAML, which needs a few pieces of information from your Amplify Auth resource.

![Entra ID set up single sign-on page with a form requiring an entity ID and reply URL](/images/auth/examples/microsoft-entra-id-saml/entra-id-set-up-saml.png)

In the **Basic SAML Configuration** step, select **Edit** and populate with the appropriate values.

| Label | Value |
|-------|-------|
| Identifier (Entity ID) | `urn:amazon:cognito:sp:<your-cognito-user-pool-id>` |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if I do this for sandbox and then need to deploy to prod, that URL will no longer be the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, though the concept is the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a callout at the top of the page

| Reply URL (Assertion Consumer Service URL) | `https://<your-cognito-domain>/saml2/idpresponse` |
| Logout Url (Optional) | `https://<your-cognito-domain>/saml2/logout` |

<Callout info>

**Note:** Amazon Cognito redirect URIs for SAML providers follow the convention:

```text showLineNumbers={false}
https://<some-hash>.auth.<aws-region>.amazoncognito.com/saml2/<action>
```

If you are using a custom domain the route remains the same: `/saml2/<action>`. [Learn more about configuring Amazon Cognito with SAML identity providers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp.html)

</Callout>

<Callout warning>

**Warning:** there is a known limitation where upstream sign-out functionality successfully signs out of Entra ID, but fails to redirect back to the user app. This behavior is disabled by default with SAML integrations in Amplify Auth.

</Callout>

Save the configuration and proceed to Step 3's **SAML Certificates** section. Copy the **App Federation Metadata Url**

![Entra ID set up single sign-on page highlighting the app federation metadata URL](/images/auth/examples/microsoft-entra-id-saml/entra-id-copy-federation-url.png)

## Configure Amplify Auth with Entra ID
josefaidt marked this conversation as resolved.
Show resolved Hide resolved

Now that you've configured your SAML provider with Microsoft Entra ID and copied the **App Federation Metadata Url**, configure your Amplify Auth resource with the new SAML provider and paste the URL value into the `metadataContent` property:

```ts title="amplify/auth/resource.ts"
import { defineAuth } from "@aws-amplify/backend"

/**
* Define and configure your auth resource
* @see https://docs.amplify.aws/gen2/build-a-backend/auth
*/
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
saml: {
name: "MicrosoftEntraIDSAML",
metadata: {
metadataType: "URL",
metadataContent: "<your-metadata-content-url>",
},
attributeMapping: {
email: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
},
},
logoutUrls: ["http://localhost:3000/come-back-soon"],
callbackUrls: ["http://localhost:3000/profile"],
},
},
})
```

User attributes can be found in Step 2's **Attributes & Claims** section, and are prefixed with a namespace by default. The example above shows mapping the default claim for the SAML user's email address, however additional attributes can be mapped.

## Optionally upload the Cognito Signing Certificate

In the AWS Console, navigate to your Cognito User Pool. Select the identity provider, **MicrosoftEntraIDSAML**, created after configuring Amplify Auth with the Entra ID SAML provider. Select **View signing certificate** and **download as .crt**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wish there was an easy way to do this through sandbox.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can note this for later. thankfully this is optional and a one time action per deployment


![Amazon Cognito console highlighting "view signing certificate" for SAML provider](/images/auth/examples/microsoft-entra-id-saml/cognito-view-signing-certificate.png)

Rename the file extension to `.cer` in order to upload to Azure. On the **Single sign-on** page, scroll down to **Step 3** (**SAML Certificates**), and under **Verification Certificates (optional)**, select **Edit**.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the file extension to .cer in order to upload to Azure.

I can add an explainer here if needbe, but in short, this form in Azure lets you select a .crt file but doesn't upload. However, it works without renaming if you're configuring a regular App Client as opposed to this Enterprise App


![Entra ID single sign-on page highlighting "edit" for verification certificates](/images/auth/examples/microsoft-entra-id-saml/entra-id-edit-verification-certificate.png)

Select **Require verification certificates** and upload the certificate.

![Entra ID verification certificate upload pane](/images/auth/examples/microsoft-entra-id-saml/entra-id-upload-verification-certificate.png)

Save your changes, and now requests to Entra ID from your Cognito User Pool will be verified.

## Connect your frontend

Now you're users are ready to sign in with Microsoft Entra ID. To sign in with this custom provider, specify the provider name as the name specified in your Amplify Auth definition: `MicrosoftEntraIDSAML`
josefaidt marked this conversation as resolved.
Show resolved Hide resolved

<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>

```ts title="main.ts"
import { signInWithRedirect } from "aws-amplify/auth"

signInWithRedirect({
provider: { custom: "MicrosoftEntraIDSAML" }
})
```

</InlineFilter>
<InlineFilter filters={["android"]}>

{/* @todo */}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we fill these in before merging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes


</InlineFilter>
<InlineFilter filters={["flutter"]}>

{/* @todo */}

</InlineFilter>
<InlineFilter filters={["swift"]}>

{/* @todo */}

</InlineFilter>