fix: auth strategy exp (#6945)

## Description

Ensures that exp and auth strategy are available from the `me` and
`refresh` operations as well as passed through the `Auth` provider. Same
as #6943

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)
This commit is contained in:
James Mikrut
2024-06-26 14:42:20 -04:00
committed by GitHub
parent ed73dedd14
commit 5ffc5a1248
7 changed files with 95 additions and 71 deletions

View File

@@ -1,16 +1,20 @@
import type { Collection } from 'payload'
import { isolateObjectProperty, meOperation } from 'payload'
import { extractJWT, isolateObjectProperty, meOperation } from 'payload'
import type { Context } from '../types.js'
function meResolver(collection: Collection): any {
async function resolver(_, args, context: Context) {
const currentToken = extractJWT(context.req)
const options = {
collection,
currentToken,
depth: 0,
req: isolateObjectProperty(context.req, 'transactionID'),
}
const result = await meOperation(options)
if (collection.config.auth.removeTokenFromResponses) {

View File

@@ -379,6 +379,9 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
exp: {
type: GraphQLInt,
},
strategy: {
type: GraphQLString,
},
token: {
type: GraphQLString,
},
@@ -405,6 +408,9 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
refreshedToken: {
type: GraphQLString,
},
strategy: {
type: GraphQLString,
},
user: {
type: collection.graphQL.JWT,
},

View File

@@ -7,6 +7,7 @@ import type { ClientUser, User } from '../types.js'
export type MeOperationResult = {
collection?: string
exp?: number
strategy?: string
token?: string
user?: ClientUser
}
@@ -49,6 +50,7 @@ export const meOperation = async ({
result = {
collection: req.user.collection,
strategy: req.user._strategy,
user,
}

View File

@@ -14,6 +14,7 @@ import { getFieldsToSign } from '../getFieldsToSign.js'
export type Result = {
exp: number
refreshedToken: string
strategy?: string
user: Document
}
@@ -88,6 +89,7 @@ export const refreshOperation = async (incomingArgs: Arguments): Promise<Result>
let result: Result = {
exp,
refreshedToken,
strategy: args.req.user._strategy,
user,
}

View File

@@ -23,7 +23,9 @@ export type AuthContext<T = ClientUser> = {
refreshPermissions: () => Promise<void>
setPermissions: (permissions: Permissions) => void
setUser: (user: T) => void
strategy?: string
token?: string
tokenExpiration?: number
user?: T | null
}
@@ -36,6 +38,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const [user, setUser] = useState<ClientUser | null>()
const [tokenInMemory, setTokenInMemory] = useState<string>()
const [tokenExpiration, setTokenExpiration] = useState<number>()
const [strategy, setStrategy] = useState<string>()
const pathname = usePathname()
const router = useRouter()
// const { code } = useLocale()
@@ -76,6 +79,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const revokeTokenAndExpire = useCallback(() => {
setTokenInMemory(undefined)
setTokenExpiration(undefined)
setStrategy(undefined)
}, [])
const setTokenAndExpiration = useCallback(
@@ -84,6 +88,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
if (token && json?.exp) {
setTokenInMemory(token)
setTokenExpiration(json.exp)
if (json.strategy) setStrategy(json.strategy)
} else {
revokeTokenAndExpire()
}
@@ -258,6 +263,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
searchParams,
admin,
revokeTokenAndExpire,
strategy,
tokenExpiration,
loginRoute,
])

View File

@@ -8,122 +8,123 @@
export interface Config {
collections: {
posts: Post
users: User
'payload-preferences': PayloadPreference
'payload-migrations': PayloadMigration
}
posts: Post;
users: User;
'payload-preferences': PayloadPreference;
'payload-migrations': PayloadMigration;
};
globals: {
menu: Menu
}
locale: null
menu: Menu;
};
locale: null;
user: User & {
collection: 'users'
}
collection: 'users';
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "posts".
*/
export interface Post {
id: string
text?: string | null
id: string;
text?: string | null;
richText?: {
root: {
type: string
type: string;
children: {
type: string
version: number
[k: string]: unknown
}[]
direction: ('ltr' | 'rtl') | null
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''
indent: number
version: number
}
[k: string]: unknown
} | null
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
} | null;
richText2?: {
root: {
type: string
type: string;
children: {
type: string
version: number
[k: string]: unknown
}[]
direction: ('ltr' | 'rtl') | null
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''
indent: number
version: number
}
[k: string]: unknown
} | null
updatedAt: string
createdAt: string
_status?: ('draft' | 'published') | null
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
} | null;
updatedAt: string;
createdAt: string;
_status?: ('draft' | 'published') | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users".
*/
export interface User {
id: string
updatedAt: string
createdAt: string
email: string
resetPasswordToken?: string | null
resetPasswordExpiration?: string | null
salt?: string | null
hash?: string | null
loginAttempts?: number | null
lockUntil?: string | null
password?: string | null
id: string;
updatedAt: string;
createdAt: string;
email: string;
resetPasswordToken?: string | null;
resetPasswordExpiration?: string | null;
salt?: string | null;
hash?: string | null;
loginAttempts?: number | null;
lockUntil?: string | null;
password?: string | null;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string
id: string;
user: {
relationTo: 'users'
value: string | User
}
key?: string | null
relationTo: 'users';
value: string | User;
};
key?: string | null;
value?:
| {
[k: string]: unknown
[k: string]: unknown;
}
| unknown[]
| string
| number
| boolean
| null
updatedAt: string
createdAt: string
| null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string
name?: string | null
batch?: number | null
updatedAt: string
createdAt: string
id: string;
name?: string | null;
batch?: number | null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "menu".
*/
export interface Menu {
id: string
globalText?: string | null
updatedAt?: string | null
createdAt?: string | null
id: string;
globalText?: string | null;
updatedAt?: string | null;
createdAt?: string | null;
}
declare module 'payload' {
// @ts-ignore
export interface GeneratedTypes extends Config {}

View File

@@ -134,6 +134,8 @@ describe('Auth', () => {
const data = await response.json()
expect(data.strategy).toBeDefined()
expect(typeof data.exp).toBe('number')
expect(response.status).toBe(200)
expect(data.user.email).toBeDefined()
})