-
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
base: feat/server-auth/main
Are you sure you want to change the base?
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.
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?
); | ||
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.
oAuthConfig, | ||
setCookieOptions, | ||
}) => { | ||
const { [IS_SIGNING_OUT_COOKIE_NAME]: isSigningOut } = |
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.
Clarification question, how is this isSigningOut
cookie used?
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.
When isSigningOut
is true
proceed with handleSignOutCallback
otherwise client is doing something wrong.
setCookieOptions, | ||
type, | ||
}) => { | ||
const { codeVerifier, state } = createAuthFlowProofs({ customState }); |
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.
Clarify question: do we need to return early if CX is already signed in?
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.
Yes, that's what's the next PR adds: #13839
httpOnly: true, | ||
secure: true, | ||
sameSite: 'lax' as const, | ||
expires: new Date(Date.now() + AUTH_FLOW_PROOF_COOKIE_EXPIRY), |
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 need to count for clock drift here? Maybe it's handled in the orchestrator, but just want to double check.
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 - should use maxAge
attribute here to avoid concerns of clock drift. Will update.
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 will do this in a separate PR.
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.
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.
…ide auth…ide auth…ide auth