-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
feat(adapter-nextjs): server-side auth flows integrating cognito hosted UI #13827
feat(adapter-nextjs): server-side auth flows integrating cognito hosted UI #13827
Conversation
"alwaysStrict": true | ||
"alwaysStrict": true, | ||
"lib": [ | ||
"esnext" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The base tsconfig has jsdom as a lib, that makes origin
variable a legit global variable which is not desired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing impl. moved out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing impl. moved out.
6087817
to
ae36b32
Compare
path: '/', | ||
httpOnly: true, | ||
secure: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These three attributes are not configurable.
ae36b32
to
621d0cb
Compare
25c4eaa
to
26ec9ed
Compare
621d0cb
to
284acbf
Compare
26ec9ed
to
67d073f
Compare
284acbf
to
0ef2b81
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost done with review, I should be able to wrap up soon.
packages/adapter-nextjs/src/auth/utils/getSearchParamValueFromUrl.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/utils/getCookieValuesFromRequest.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/utils/resolveIdentityProviderFromUrl.ts
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/utils/getCookieValuesFromNextApiRequest.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/handlers/handleSignOutCallbackRequestForPagesRouter.ts
Show resolved
Hide resolved
const decoded = decodeJWT(accessToken); | ||
const issuedAt = (decoded.payload.iat ?? 0) * 1000; | ||
const clockDrift = issuedAt > 0 ? issuedAt - Date.now() : 0; | ||
const username = (decoded.payload.username as string) ?? 'username'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there valid scenarios when username would be missing from payload or any particular reasoning around default username
to "username"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. I just followed the original client-side impl.
This is a good question, let me dig and get back to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The username
in the token payload corresponds the username
in a Cognito user pool, and the username
of a user in a Cognito user pool is always defined. From this I think we can safely remove the redundant default value fallback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, thanks for looking into this.
packages/adapter-nextjs/src/auth/handlers/handleSignOutRequestForPagesRouter.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/handlers/handleSignInSignUpRequestForPagesRouter.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/__tests__/auth/utils/tokenCookies.test.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/__tests__/auth/utils/getAccessTokenUsernameAndClockDrift.test.ts
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/utils/createOnSignInCompletedRedirectIntermediate.ts
Outdated
Show resolved
Hide resolved
packages/adapter-nextjs/src/auth/handlers/handleSignInCallbackRequestForPagesRouter.ts
Outdated
Show resolved
Hide resolved
0ef2b81
to
ff48e7a
Compare
packages/adapter-nextjs/src/auth/handlers/handleSignOutCallbackRequest.ts
Show resolved
Hide resolved
}) => { | ||
const { code, state } = resolveCodeAndStateFromUrl(request.url); | ||
if (!code || !state) { | ||
return new Response(null, { status: 400 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we see needs for customers to customize the error payloads and render different messages accordingly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question - This particular spot is for unwrapping code
and state
to defined strings, and here it's redirecting back from Hosted UI endpoint, they should always be provided.
Though in the current implementation we are returning 400 response when state
and pkce
cookies are not presented (expired in 10 minutes without the end user completing the sign in) I will keep the implementation as is and looking into how to surface an error for this situation.
); | ||
appendSetCookieHeaders( | ||
headers, | ||
createSignInFlowProofCookies({ state: '', pkce: '' }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit: prefer to re-name this locally to callout the cookie removal, similar to the next line. Something like
createSignInFlowProofRemoveCookies(),
Which is also a similar practice to the createTokenRemoveCookies
below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function sets only cookie name-value - which is not add or remove specific. The only difference is on the options.
packages/adapter-nextjs/src/auth/handlers/handleSignOutCallbackRequestForPagesRouter.ts
Show resolved
Hide resolved
oAuthConfig: OAuthConfig, | ||
) => { | ||
const redirectUrl = oAuthConfig.redirectSignIn.find(url => | ||
url.startsWith(origin), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use the URL
util and parse the origin from the oAuthConfig
more strictly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's necessary to construct a URL object from the config redirect URL strings - as a client-side validation this should be good enough, as eventually HostedUI will also match the URL on the service side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is startsWith
sufficient to handle different domains but with the same subdomains, e.g. sub.abc.io
v.s. sub.abc.io.com
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the origin
remain unchanged (configured once by env var) as the predicate to look up a corresponding url from redirectURLs, and we are match origin starting from the protocol rather than a domain, I still think it's sufficient.
a585318
to
56dd741
Compare
…ed UI (#13827) * chore(auth): export necessary utilities and types to support server-side auth * chore(aws-amplify): export necessary utilities to support server-side auth * feat(adapter-nextjs): server-side auth api route integrating cognito hosted ui * chore(adapter-nextjs): resolve comments * refactor(adapter-nextjs): remove redundant username fallback
Description of changes
Implemented the following flow integrating Cognito Hosted UI endpoints:
API Route handlers work with both Next.js App Router and Pages Router.
Issue #, if available
Description of how you validated changes
Checklist
yarn test
passesChecklist for repo maintainers
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.