Skip to content

Commit

Permalink
Merge pull request #10 from fief-dev/nextjs/ssr
Browse files Browse the repository at this point in the history
nextjs: implement SSR functions to retrieve user and access token info
  • Loading branch information
frankie567 authored Jun 4, 2024
2 parents 94d515b + 2977b29 commit fa72922
Show file tree
Hide file tree
Showing 20 changed files with 2,381 additions and 1,939 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"node": true,
"jest/globals": true
},
"globals": {
"RequestInit": true
},
"ignorePatterns": [
"build/"
],
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
}
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"javascript"
Expand Down
10 changes: 7 additions & 3 deletions nextjs/react/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"name": "@fief/fief/nextjs/react",
"private": true,
"main": "../../build/cjs/nextjs/react.js",
"module": "../../build/esm/nextjs/react.js",
"types": "../../build/esm/nextjs/react.d.ts"
"main": "../../build/cjs/nextjs/react/index.js",
"module": "../../build/esm/nextjs/react/index.js",
"types": "../../build/esm/nextjs/react/index.d.ts",
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
3,607 changes: 1,924 additions & 1,683 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3",
"jest-location-mock": "^2.0.0",
"next": "^13.2.4",
"next": "^14.2.3",
"node-fetch": "^2.7.0",
"node-mocks-http": "^1.11.0",
"ramda": "^0.29.0",
Expand All @@ -74,7 +74,7 @@
},
"dependencies": {
"encoding": "^0.1.13",
"jose": "^4.6.0",
"jose": "^5.4.0",
"path-to-regexp": "^6.2.1"
},
"jest": {}
Expand Down
12 changes: 10 additions & 2 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ const external = [
'crypto',
'jose',
'next',
'next/cache',
'next/headers',
'next/server',
'path-to-regexp',
'react',
'react/jsx-runtime',
];
const globals = {
crypto: 'crypto',
};

export default [
// browser-friendly UMD build
Expand All @@ -23,6 +28,7 @@ export default [
file: 'build/index.umd.js',
format: 'umd',
sourcemap: true,
globals,
},
plugins: [
nodeResolve({
Expand All @@ -43,7 +49,7 @@ export default [
'src/react/index.ts',
'src/express/index.ts',
'src/nextjs/index.ts',
'src/nextjs/react.tsx',
'src/nextjs/react/index.ts',
],
plugins: [
typescript({
Expand All @@ -59,6 +65,7 @@ export default [
sourcemap: true,
preserveModules: true,
preserveModulesRoot: 'src',
globals,
},
],
external,
Expand All @@ -70,7 +77,7 @@ export default [
'src/react/index.ts',
'src/express/index.ts',
'src/nextjs/index.ts',
'src/nextjs/react.tsx',
'src/nextjs/react/index.ts',
],
plugins: [
typescript({
Expand All @@ -87,6 +94,7 @@ export default [
sourcemap: true,
preserveModules: true,
preserveModulesRoot: 'src',
globals,
},
],
external,
Expand Down
45 changes: 44 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ export interface FiefParameters {
* @see [ID Token encryption](https://docs.fief.dev/going-further/id-token-encryption/)
*/
encryptionKey?: string;

/**
* Additional fetch init options for `getOpenIDConfiguration` and `getJWKS` requests.
*
* Mostly useful to control fetch cache.
*
* @see [fetch cache property](https://developer.mozilla.org/en-US/docs/Web/API/Request/cache)
* @see [Next.js fetch](https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options)
*/
requestInit?: RequestInit;
}

/**
Expand All @@ -253,6 +263,8 @@ export class Fief {

private fetch: typeof fetch;

private requestInit?: RequestInit;

private openIDConfiguration?: Record<string, any>;

private jwks?: jose.JSONWebKeySet;
Expand All @@ -274,6 +286,7 @@ export class Fief {
}

this.fetch = getFetch();
this.requestInit = parameters.requestInit;

this.crypto = getCrypto();
}
Expand Down Expand Up @@ -348,6 +361,7 @@ export class Fief {
* @param redirectURI - The exact same `redirectURI` you passed to the authorization URL.
* @param codeVerifier - The raw [PKCE](https://docs.fief.dev/going-further/pkce/) code
* used to generate the code challenge during authorization.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns A token response and user information.
*
Expand All @@ -360,6 +374,7 @@ export class Fief {
code: string,
redirectURI: string,
codeVerifier?: string,
requestInit?: RequestInit,
): Promise<[FiefTokenResponse, FiefUserInfo]> {
const openIDConfiguration = await this.getOpenIDConfiguration();
const payload = serializeQueryString({
Expand All @@ -374,9 +389,11 @@ export class Fief {
const response = await this.fetch(
openIDConfiguration.token_endpoint,
{
...requestInit || {},
method: 'POST',
body: payload,
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/x-www-form-urlencoded',
},
},
Expand All @@ -402,6 +419,7 @@ export class Fief {
* If not provided, the access token will share the same list of scopes
* as requested the first time.
* Otherwise, it should be a subset of the original list of scopes.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns A token response and user information.
*
Expand All @@ -413,6 +431,7 @@ export class Fief {
public async authRefreshToken(
refreshToken: string,
scope?: string[],
requestInit?: RequestInit,
): Promise<[FiefTokenResponse, FiefUserInfo]> {
const openIDConfiguration = await this.getOpenIDConfiguration();
const payload = serializeQueryString({
Expand All @@ -425,9 +444,11 @@ export class Fief {
const response = await this.fetch(
openIDConfiguration.token_endpoint,
{
...requestInit || {},
method: 'POST',
body: payload,
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/x-www-form-urlencoded',
},
},
Expand All @@ -452,6 +473,7 @@ export class Fief {
* @param requiredScopes - Optional list of scopes to check for.
* @param requiredACR - Optional minimum ACR level required. Read more: https://docs.fief.dev/going-further/acr/
* @param requiredPermissions - Optional list of permissions to check for.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns {@link FiefAccessTokenInfo}
* @throws {@link FiefAccessTokenInvalid} if the access token is invalid.
Expand Down Expand Up @@ -548,6 +570,7 @@ export class Fief {
* Return fresh {@link FiefUserInfo} from the Fief API using a valid access token.
*
* @param accessToken - A valid access token.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns Fresh user information.
*
Expand All @@ -556,13 +579,15 @@ export class Fief {
* userinfo = await fief.userinfo('ACCESS_TOKEN');
* ```
*/
public async userinfo(accessToken: string): Promise<FiefUserInfo> {
public async userinfo(accessToken: string, requestInit?: RequestInit): Promise<FiefUserInfo> {
const openIDConfiguration = await this.getOpenIDConfiguration();
const response = await this.fetch(
openIDConfiguration.userinfo_endpoint,
{
...requestInit || {},
method: 'GET',
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
Authorization: `Bearer ${accessToken}`,
},
},
Expand All @@ -577,6 +602,7 @@ export class Fief {
*
* @param accessToken - A valid access token.
* @param data - An object containing the data to update.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns Updated user information.
*
Expand All @@ -590,14 +616,17 @@ export class Fief {
public async updateProfile(
accessToken: string,
data: Record<string, any>,
requestInit?: RequestInit,
): Promise<FiefUserInfo> {
const updateProfileEndpoint = `${this.baseURL}/api/profile`;
const response = await this.fetch(
updateProfileEndpoint,
{
...requestInit || {},
method: 'PATCH',
body: JSON.stringify(data),
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
Expand All @@ -615,6 +644,7 @@ export class Fief {
*
* @param accessToken - A valid access token.
* @param newPassword - The new password.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns Updated user information.
*
Expand All @@ -626,14 +656,17 @@ export class Fief {
public async changePassword(
accessToken: string,
newPassword: string,
requestInit?: RequestInit,
): Promise<FiefUserInfo> {
const updateProfileEndpoint = `${this.baseURL}/api/password`;
const response = await this.fetch(
updateProfileEndpoint,
{
...requestInit || {},
method: 'PATCH',
body: JSON.stringify({ password: newPassword }),
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
Expand All @@ -654,6 +687,7 @@ export class Fief {
*
* @param accessToken - A valid access token.
* @param newPassword - The new email address.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns Updated user information.
*
Expand All @@ -665,14 +699,17 @@ export class Fief {
public async emailChange(
accessToken: string,
email: string,
requestInit?: RequestInit,
): Promise<FiefUserInfo> {
const updateProfileEndpoint = `${this.baseURL}/api/email/change`;
const response = await this.fetch(
updateProfileEndpoint,
{
...requestInit || {},
method: 'PATCH',
body: JSON.stringify({ email }),
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
Expand All @@ -691,6 +728,7 @@ export class Fief {
*
* @param accessToken - A valid access token.
* @param newPassword - The new email address.
* @param requestInit - Additional fetch init options. Mostly useful to control fetch cache.
*
* @returns Updated user information.
*
Expand All @@ -702,14 +740,17 @@ export class Fief {
public async emailVerify(
accessToken: string,
code: string,
requestInit?: RequestInit,
): Promise<FiefUserInfo> {
const updateProfileEndpoint = `${this.baseURL}/api/email/verify`;
const response = await this.fetch(
updateProfileEndpoint,
{
...requestInit || {},
method: 'POST',
body: JSON.stringify({ code }),
headers: {
...requestInit && requestInit.headers ? requestInit.headers : {},
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
Expand Down Expand Up @@ -752,6 +793,7 @@ export class Fief {
const response = await this.fetch(
`${this.baseURL}/.well-known/openid-configuration`,
{
...this.requestInit || {},
method: 'GET',
},
);
Expand All @@ -771,6 +813,7 @@ export class Fief {
const response = await this.fetch(
openIDConfiguration.jwks_uri,
{
...this.requestInit || {},
method: 'GET',
},
);
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ export const getCrypto = (): ICryptoHelper => {
throw new CryptoHelperError('Cannot find a crypto implementation for your environment');
};

export { CryptoHelperError, ICryptoHelper };
export { CryptoHelperError };
export type { ICryptoHelper };
4 changes: 3 additions & 1 deletion src/express/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,12 @@ const createMiddleware = (parameters: FiefAuthParameters) => {
};

export {
AuthenticateRequestParameters,
authorizationSchemeGetter,
cookieGetter,
createMiddleware,
};
export type {
AuthenticateRequestParameters,
IUserInfoCache,
TokenGetter,
};
Loading

0 comments on commit fa72922

Please sign in to comment.