Skip to content

Commit b1c5095

Browse files
committedMar 17, 2025··
Update example for FCAT
1 parent cdbbe6e commit b1c5095

File tree

2 files changed

+128
-14
lines changed

2 files changed

+128
-14
lines changed
 

‎EXAMPLES.md

+127-13
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
- [Custom routes](#custom-routes)
3333
- [Testing helpers](#testing-helpers)
3434
- [`generateSessionCookie`](#generatesessioncookie)
35+
- [Getting access tokens for connections](#getting-access-tokens-for-connections)
36+
- [On the server (App Router)](#on-the-server-app-router-3)
37+
- [On the server (Pages Router)](#on-the-server-pages-router-3)
38+
- [Middleware](#middleware-3)
3539

3640
## Passing authorization parameters
3741

@@ -754,22 +758,132 @@ const sessionCookieValue = await generateSessionCookie(
754758
```
755759

756760
## Getting access tokens for connections
757-
You can retrieve access tokens for connections using the `getAccessTokenForConnection()` method of `AuthClient`.
758-
This is an async method and can be run either from middleware, a client page or a server rendered page.
759-
Note that to cache these tokens retrieved from auth0, this needs to be called in the middleware:
761+
You can retrieve an access token for a connection using the `getAccessTokenForConnection()` method, which accepts an object with the following properties:
762+
- `connection`: The federated connection for which an access token should be retrieved.
763+
- `login_hint`: The optional login_hint parameter to pass to the `/authorize` endpoint.
764+
765+
### On the server (App Router)
766+
767+
On the server, the `getAccessTokenForConnection()` helper can be used in Server Routes, Server Actions and Server Components to get an access token for a connection.
768+
769+
> [!IMPORTANT]
770+
> Server Components cannot set cookies. Calling `getAccessTokenForConnection()` in a Server Component will cause the access token to be refreshed, if it is expired, and the updated token set will not to be persisted.
771+
>
772+
> It is recommended to call `getAccessTokenForConnection(req, res)` in the middleware if you need to refresh the token in a Server Component as this will ensure the token is refreshed and correctly persisted.
773+
774+
For example:
775+
776+
```ts
777+
import { NextResponse } from "next/server"
778+
779+
import { auth0 } from "@/lib/auth0"
780+
781+
export async function GET() {
782+
try {
783+
const token = await auth0.getAccessTokenForConnection({ connection: 'google-oauth2' })
784+
// call external API with token...
785+
} catch (err) {
786+
// err will be an instance of AccessTokenError if an access token could not be obtained
787+
}
788+
789+
return NextResponse.json({
790+
message: "Success!",
791+
})
792+
}
793+
```
794+
795+
### On the server (Pages Router)
796+
797+
On the server, the `getAccessTokenForConnection({}, req, res)` helper can be used in `getServerSideProps` and API routes to get an access token for a connection, like so:
798+
799+
```ts
800+
import type { NextApiRequest, NextApiResponse } from "next"
801+
802+
import { auth0 } from "@/lib/auth0"
803+
804+
export default async function handler(
805+
req: NextApiRequest,
806+
res: NextApiResponse<{ message: string }>
807+
) {
808+
try {
809+
const token = await auth0.getAccessTokenForConnection({ connection: 'google-oauth2' }, req, res)
810+
} catch (err) {
811+
// err will be an instance of AccessTokenError if an access token could not be obtained
812+
}
813+
814+
res.status(200).json({ message: "Success!" })
815+
}
816+
```
817+
818+
### Middleware
819+
820+
In middleware, the `getAccessTokenForConnection({}, req, res)` helper can be used to get an access token for a connection, like so:
821+
822+
```tsx
823+
import { NextRequest, NextResponse } from "next/server"
824+
825+
import { auth0 } from "@/lib/auth0"
760826

761-
```typescript
762827
export async function middleware(request: NextRequest) {
763-
const authResponse = await auth0.middleware(request);
764-
const session = await auth0.getSession();
765-
if (session) {
766-
// cache token for google connection to session store
767-
console.log(await auth0.getAccessTokenForConnection({connection: 'google-oauth2'}));
828+
const authRes = await auth0.middleware(request)
829+
830+
if (request.nextUrl.pathname.startsWith("/auth")) {
831+
return authRes
832+
}
833+
834+
const session = await auth0.getSession(request)
835+
836+
if (!session) {
837+
// user is not authenticated, redirect to login page
838+
return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin))
768839
}
769-
return authResponse
840+
841+
const accessToken = await auth0.getAccessTokenForConnection({ connection: 'google-oauth2' }, request, authRes)
842+
843+
// the headers from the auth middleware should always be returned
844+
return authRes
770845
}
771846
```
772-
`connection` parameter is the federated connection string for the provider.
773-
Here, we are accessing the token for `google-oauth2` connection.
774847

775-
Upon further calls for the same provider, the cached value will be used until it expires.
848+
> [!IMPORTANT]
849+
> The `request` and `response` objects must be passed as a parameters to the `getAccessTokenForConnection({}, request, response)` method when called from a middleware to ensure that the refreshed access token can be accessed within the same request.
850+
851+
If you are using the Pages Router and are calling the `getAccessTokenForConnection` method in both the middleware and an API Route or `getServerSideProps`, it's recommended to propagate the headers from the middleware, as shown below. This will ensure that calling `getAccessTokenForConnection` in the API Route or `getServerSideProps` will not result in the access token being refreshed again.
852+
853+
```ts
854+
import { NextRequest, NextResponse } from "next/server"
855+
856+
import { auth0 } from "@/lib/auth0"
857+
858+
export async function middleware(request: NextRequest) {
859+
const authRes = await auth0.middleware(request)
860+
861+
if (request.nextUrl.pathname.startsWith("/auth")) {
862+
return authRes
863+
}
864+
865+
const session = await auth0.getSession(request)
866+
867+
if (!session) {
868+
// user is not authenticated, redirect to login page
869+
return NextResponse.redirect(new URL("/auth/login", request.nextUrl.origin))
870+
}
871+
872+
const accessToken = await auth0.getAccessTokenForConnection({ connection: 'google-oauth2' }, request, authRes)
873+
874+
// create a new response with the updated request headers
875+
const resWithCombinedHeaders = NextResponse.next({
876+
request: {
877+
headers: request.headers,
878+
},
879+
})
880+
881+
// set the response headers (set-cookie) from the auth response
882+
authRes.headers.forEach((value, key) => {
883+
resWithCombinedHeaders.headers.set(key, value)
884+
})
885+
886+
// the headers from the auth middleware should always be returned
887+
return resWithCombinedHeaders
888+
}
889+
```

‎src/types/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export interface AccessTokenForConnectionOptions {
105105
connection: string;
106106

107107
/**
108-
* An optiona login hint to pass to the authorization server.
108+
* An optional login hint to pass to the authorization server.
109109
*/
110110
login_hint?: string;
111111
}

0 commit comments

Comments
 (0)
Please sign in to comment.