-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b7e7cfc
commit 5661f65
Showing
32 changed files
with
6,275 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
NEXT_PUBLIC_SAML_GENERATION_URL="https://example.com/generateSaml" | ||
NEXT_PUBLIC_COGNITO_HOSTED_UI_URL="https://example.com" | ||
NEXT_PUBLIC_COGNITO_CLIENT_ID="cl1en4_1D" | ||
NEXT_PUBLIC_COGNITO_REDIRECT_URI="http://localhost:3000" | ||
NEXT_PUBLIC_SSO_DEFAULT_DURATION=28800 | ||
NEXT_PUBLIC_AWS_SAML_ENDPOINT="https://example.com/saml" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Automated testing | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Use Node.js 20.x | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: 20.x | ||
- name: Install dependencies | ||
run: npm ci | ||
- name: Run ESLint | ||
run: npm run lint | ||
- name: Run Cypress tests | ||
uses: cypress-io/github-action@v6 | ||
with: | ||
browser: chrome | ||
start: npm run dev | ||
wait-on: "http://localhost:3000" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
.pnpm-debug.log* | ||
|
||
# local env files | ||
.env.development.local | ||
.env.production.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
engine-strict=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,53 @@ | ||
# aws-connect-sso-web-app | ||
# AWS Connect SSO Web App | ||
|
||
This project is intended to run from AWS Amplify, using Cognito as the log in | ||
mechanism with users configured to have specialized groups representing their | ||
Call Center permissions for various AWS Connect instances. This works in concert | ||
with the Lambda defined for | ||
[generating SAML Responses for Connect](https://github.com/newjersey/custom-aws-idp). | ||
Then, once a user logs in to Cognito, this site should help them (within zero to | ||
two clicks) get federated and logged in to their desired Connect instance. | ||
|
||
## Configuration | ||
|
||
This site relies on some environment variables: | ||
|
||
- `NEXT_PUBLIC_SAML_GENERATION_URL` | ||
|
||
The URL for the APIGateway connection to the SAML Response generating Lambda | ||
mentioned above | ||
|
||
- `NEXT_PUBLIC_COGNITO_HOSTED_UI_URL` | ||
|
||
The base URL for the Hosted UI Cognito sign-in page associated with this | ||
UserPool's application (the current working UserPool is "_Cognito for Connect | ||
Call Centers_" (ID: _us-east-1_jKQHCtx7s_) and the "App integration" client is | ||
"_ReactAppClient_") | ||
|
||
- `NEXT_PUBLIC_COGNITO_CLIENT_ID` | ||
|
||
The Client ID of the App Integration - App Client (from the "_ReactAppClient_" | ||
client) | ||
|
||
- `NEXT_PUBLIC_COGNITO_REDIRECT_URI` | ||
|
||
The URL of this web app | ||
|
||
**Note:** This must be configured here as well as inside Cognito, in the | ||
UserPool, in the App client, under "_Hosted UI_", under "_Allowed callback | ||
URLs_" | ||
|
||
- `NEXT_PUBLIC_SSO_DEFAULT_DURATION` | ||
|
||
The session duration to use for the SSO session requested by the generated | ||
SAML (in seconds) | ||
|
||
- `NEXT_PUBLIC_AWS_SAML_ENDPOINT` | ||
|
||
The SAML endpoint for Connect SSO sessions (should be | ||
"https://signin.aws.amazon.com/saml") | ||
|
||
## Misc | ||
|
||
This is a [Next.js](https://nextjs.org/) project bootstrapped with | ||
[`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import React, { useState } from "react"; | ||
import generateSaml from "../pages/api/generateSaml"; | ||
import { CallCenterSubmitState, SsoDetails } from "../pages/api/types"; | ||
import styles from "../styles/Home.module.css"; | ||
|
||
interface Props { | ||
cognitoGroups: string[]; | ||
idToken: string; | ||
submitState: CallCenterSubmitState; | ||
setSubmitState: React.Dispatch<React.SetStateAction<CallCenterSubmitState>>; | ||
setSsoDetails: React.Dispatch<React.SetStateAction<SsoDetails | undefined>>; | ||
setError: React.Dispatch<React.SetStateAction<string | undefined>>; | ||
} | ||
|
||
/** | ||
* Pick one call center with a radio button type of form when a user is | ||
* configured with multiple call centers. | ||
* | ||
* @param cognitoGroups The groups (call centers) this user belongs to | ||
* @param idToken User's Cognito token necessary for calling `generateSaml` | ||
* @param submitState Enum state variable denoting the current submit-state for | ||
* a call center choice | ||
* @param setSubmitState Setter for the above state variable | ||
* @param setSsoDetails Setter for the output of `generateSaml` | ||
* @param setError Setter in case there are errors while calling `generateSaml` | ||
*/ | ||
export default function CallCenterPicker({ | ||
cognitoGroups, | ||
idToken, | ||
submitState, | ||
setSubmitState, | ||
setSsoDetails, | ||
setError, | ||
}: Props) { | ||
const [currentPick, setCurrentPick] = useState<string | undefined>(undefined); | ||
const onRadioGroupSubmit = () => { | ||
setSubmitState(CallCenterSubmitState.USER_SUBMITTED); | ||
generateSaml(currentPick!, idToken) | ||
.then((output) => setSsoDetails(output)) | ||
.catch((error) => setError(error.message)); | ||
}; | ||
|
||
return ( | ||
<> | ||
<h2>Choose a Call Center to connect to:</h2> | ||
<div> | ||
{cognitoGroups.map((group: string) => ( | ||
<div key={group}> | ||
<input | ||
type="radio" | ||
name="currentGroupChoice" | ||
value={group} | ||
id={group} | ||
checked={currentPick === group} | ||
onChange={(e) => setCurrentPick(e.target.value)} | ||
/> | ||
<label htmlFor={group}>{group}</label> | ||
</div> | ||
))} | ||
</div> | ||
<div> | ||
<button | ||
className={styles.button} | ||
disabled={ | ||
currentPick == undefined || | ||
submitState === CallCenterSubmitState.USER_SUBMITTED | ||
} | ||
onClick={onRadioGroupSubmit} | ||
> | ||
Connect | ||
</button> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { useEffect, useRef } from "react"; | ||
import { AWS_SAML_ENDPOINT } from "../pages/api/constants"; | ||
import { SsoDetails } from "../pages/api/types"; | ||
|
||
interface Props { | ||
ssoDetails: SsoDetails | undefined; | ||
} | ||
|
||
/** | ||
* A special form designed to POST the SAML SSO details to AWS. It is also | ||
* designed to auto-submit the form when the `ssoDetails` become defined. SAML | ||
* logins work best when the POST as well as subsequent interactions are managed | ||
* by the browser, but a user with only one configured Call Center should not | ||
* have to click anything to submit this form. Thus, the form is intentionally | ||
* hidden and set to auto-submit utilizing an effect hook. | ||
* | ||
* @param ssoDetails State variable containing the details used by the SSO form | ||
*/ | ||
export default function SelfSubmittingSsoForm({ ssoDetails }: Props) { | ||
// Refs seem to need `null` instead of `undefined` | ||
const formRef = useRef<HTMLFormElement | null>(null); | ||
const samlResponseRef = useRef<HTMLInputElement | null>(null); | ||
const relayStateRef = useRef<HTMLInputElement | null>(null); | ||
|
||
// Auto-submit the SAML form once ssoDetails are present | ||
useEffect(() => { | ||
if ( | ||
samlResponseRef.current?.value != null && | ||
samlResponseRef.current.value.length > 0 && | ||
relayStateRef.current?.value != null && | ||
relayStateRef.current.value.length > 0 | ||
) { | ||
formRef.current?.submit(); | ||
} | ||
}, [samlResponseRef.current?.value, relayStateRef.current?.value]); | ||
|
||
return ( | ||
<form | ||
action={AWS_SAML_ENDPOINT} | ||
encType="application/x-www-form-urlencoded" | ||
method="POST" | ||
ref={formRef} | ||
> | ||
<input | ||
name="SAMLResponse" | ||
value={ssoDetails?.SAMLResponse ?? ""} | ||
type="hidden" | ||
ref={samlResponseRef} | ||
/> | ||
<input | ||
name="RelayState" | ||
value={ssoDetails?.RelayState ?? ""} | ||
type="hidden" | ||
ref={relayStateRef} | ||
/> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { defineConfig } from "cypress"; | ||
|
||
export default defineConfig({ | ||
e2e: { | ||
baseUrl: "http://localhost:3000", | ||
}, | ||
component: { | ||
devServer: { | ||
framework: "next", | ||
bundler: "webpack", | ||
}, | ||
}, | ||
chromeWebSecurity: false, | ||
retries: { | ||
runMode: 2, | ||
openMode: 0, | ||
}, | ||
}); |
Oops, something went wrong.