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:
@@ -1,16 +1,20 @@
|
|||||||
import type { Collection } from 'payload'
|
import type { Collection } from 'payload'
|
||||||
|
|
||||||
import { isolateObjectProperty, meOperation } from 'payload'
|
import { extractJWT, isolateObjectProperty, meOperation } from 'payload'
|
||||||
|
|
||||||
import type { Context } from '../types.js'
|
import type { Context } from '../types.js'
|
||||||
|
|
||||||
function meResolver(collection: Collection): any {
|
function meResolver(collection: Collection): any {
|
||||||
async function resolver(_, args, context: Context) {
|
async function resolver(_, args, context: Context) {
|
||||||
|
const currentToken = extractJWT(context.req)
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
collection,
|
collection,
|
||||||
|
currentToken,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
req: isolateObjectProperty(context.req, 'transactionID'),
|
req: isolateObjectProperty(context.req, 'transactionID'),
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await meOperation(options)
|
const result = await meOperation(options)
|
||||||
|
|
||||||
if (collection.config.auth.removeTokenFromResponses) {
|
if (collection.config.auth.removeTokenFromResponses) {
|
||||||
|
|||||||
@@ -379,6 +379,9 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
|
|||||||
exp: {
|
exp: {
|
||||||
type: GraphQLInt,
|
type: GraphQLInt,
|
||||||
},
|
},
|
||||||
|
strategy: {
|
||||||
|
type: GraphQLString,
|
||||||
|
},
|
||||||
token: {
|
token: {
|
||||||
type: GraphQLString,
|
type: GraphQLString,
|
||||||
},
|
},
|
||||||
@@ -405,6 +408,9 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
|
|||||||
refreshedToken: {
|
refreshedToken: {
|
||||||
type: GraphQLString,
|
type: GraphQLString,
|
||||||
},
|
},
|
||||||
|
strategy: {
|
||||||
|
type: GraphQLString,
|
||||||
|
},
|
||||||
user: {
|
user: {
|
||||||
type: collection.graphQL.JWT,
|
type: collection.graphQL.JWT,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type { ClientUser, User } from '../types.js'
|
|||||||
export type MeOperationResult = {
|
export type MeOperationResult = {
|
||||||
collection?: string
|
collection?: string
|
||||||
exp?: number
|
exp?: number
|
||||||
|
strategy?: string
|
||||||
token?: string
|
token?: string
|
||||||
user?: ClientUser
|
user?: ClientUser
|
||||||
}
|
}
|
||||||
@@ -49,6 +50,7 @@ export const meOperation = async ({
|
|||||||
|
|
||||||
result = {
|
result = {
|
||||||
collection: req.user.collection,
|
collection: req.user.collection,
|
||||||
|
strategy: req.user._strategy,
|
||||||
user,
|
user,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { getFieldsToSign } from '../getFieldsToSign.js'
|
|||||||
export type Result = {
|
export type Result = {
|
||||||
exp: number
|
exp: number
|
||||||
refreshedToken: string
|
refreshedToken: string
|
||||||
|
strategy?: string
|
||||||
user: Document
|
user: Document
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ export const refreshOperation = async (incomingArgs: Arguments): Promise<Result>
|
|||||||
let result: Result = {
|
let result: Result = {
|
||||||
exp,
|
exp,
|
||||||
refreshedToken,
|
refreshedToken,
|
||||||
|
strategy: args.req.user._strategy,
|
||||||
user,
|
user,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ export type AuthContext<T = ClientUser> = {
|
|||||||
refreshPermissions: () => Promise<void>
|
refreshPermissions: () => Promise<void>
|
||||||
setPermissions: (permissions: Permissions) => void
|
setPermissions: (permissions: Permissions) => void
|
||||||
setUser: (user: T) => void
|
setUser: (user: T) => void
|
||||||
|
strategy?: string
|
||||||
token?: string
|
token?: string
|
||||||
|
tokenExpiration?: number
|
||||||
user?: T | null
|
user?: T | null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +38,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
const [user, setUser] = useState<ClientUser | null>()
|
const [user, setUser] = useState<ClientUser | null>()
|
||||||
const [tokenInMemory, setTokenInMemory] = useState<string>()
|
const [tokenInMemory, setTokenInMemory] = useState<string>()
|
||||||
const [tokenExpiration, setTokenExpiration] = useState<number>()
|
const [tokenExpiration, setTokenExpiration] = useState<number>()
|
||||||
|
const [strategy, setStrategy] = useState<string>()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
// const { code } = useLocale()
|
// const { code } = useLocale()
|
||||||
@@ -76,6 +79,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
const revokeTokenAndExpire = useCallback(() => {
|
const revokeTokenAndExpire = useCallback(() => {
|
||||||
setTokenInMemory(undefined)
|
setTokenInMemory(undefined)
|
||||||
setTokenExpiration(undefined)
|
setTokenExpiration(undefined)
|
||||||
|
setStrategy(undefined)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const setTokenAndExpiration = useCallback(
|
const setTokenAndExpiration = useCallback(
|
||||||
@@ -84,6 +88,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
if (token && json?.exp) {
|
if (token && json?.exp) {
|
||||||
setTokenInMemory(token)
|
setTokenInMemory(token)
|
||||||
setTokenExpiration(json.exp)
|
setTokenExpiration(json.exp)
|
||||||
|
if (json.strategy) setStrategy(json.strategy)
|
||||||
} else {
|
} else {
|
||||||
revokeTokenAndExpire()
|
revokeTokenAndExpire()
|
||||||
}
|
}
|
||||||
@@ -258,6 +263,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
searchParams,
|
searchParams,
|
||||||
admin,
|
admin,
|
||||||
revokeTokenAndExpire,
|
revokeTokenAndExpire,
|
||||||
|
strategy,
|
||||||
|
tokenExpiration,
|
||||||
loginRoute,
|
loginRoute,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@@ -8,123 +8,124 @@
|
|||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
collections: {
|
collections: {
|
||||||
posts: Post
|
posts: Post;
|
||||||
users: User
|
users: User;
|
||||||
'payload-preferences': PayloadPreference
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration
|
'payload-migrations': PayloadMigration;
|
||||||
}
|
};
|
||||||
globals: {
|
globals: {
|
||||||
menu: Menu
|
menu: Menu;
|
||||||
}
|
};
|
||||||
locale: null
|
locale: null;
|
||||||
user: User & {
|
user: User & {
|
||||||
collection: 'users'
|
collection: 'users';
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "posts".
|
* via the `definition` "posts".
|
||||||
*/
|
*/
|
||||||
export interface Post {
|
export interface Post {
|
||||||
id: string
|
id: string;
|
||||||
text?: string | null
|
text?: string | null;
|
||||||
richText?: {
|
richText?: {
|
||||||
root: {
|
root: {
|
||||||
type: string
|
type: string;
|
||||||
children: {
|
children: {
|
||||||
type: string
|
type: string;
|
||||||
version: number
|
version: number;
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
}[]
|
}[];
|
||||||
direction: ('ltr' | 'rtl') | null
|
direction: ('ltr' | 'rtl') | null;
|
||||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
indent: number
|
indent: number;
|
||||||
version: number
|
version: number;
|
||||||
}
|
};
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
} | null
|
} | null;
|
||||||
richText2?: {
|
richText2?: {
|
||||||
root: {
|
root: {
|
||||||
type: string
|
type: string;
|
||||||
children: {
|
children: {
|
||||||
type: string
|
type: string;
|
||||||
version: number
|
version: number;
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
}[]
|
}[];
|
||||||
direction: ('ltr' | 'rtl') | null
|
direction: ('ltr' | 'rtl') | null;
|
||||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''
|
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||||
indent: number
|
indent: number;
|
||||||
version: number
|
version: number;
|
||||||
}
|
};
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
} | null
|
} | null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
_status?: ('draft' | 'published') | null
|
_status?: ('draft' | 'published') | null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "users".
|
* via the `definition` "users".
|
||||||
*/
|
*/
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string
|
id: string;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
email: string
|
email: string;
|
||||||
resetPasswordToken?: string | null
|
resetPasswordToken?: string | null;
|
||||||
resetPasswordExpiration?: string | null
|
resetPasswordExpiration?: string | null;
|
||||||
salt?: string | null
|
salt?: string | null;
|
||||||
hash?: string | null
|
hash?: string | null;
|
||||||
loginAttempts?: number | null
|
loginAttempts?: number | null;
|
||||||
lockUntil?: string | null
|
lockUntil?: string | null;
|
||||||
password?: string | null
|
password?: string | null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-preferences".
|
* via the `definition` "payload-preferences".
|
||||||
*/
|
*/
|
||||||
export interface PayloadPreference {
|
export interface PayloadPreference {
|
||||||
id: string
|
id: string;
|
||||||
user: {
|
user: {
|
||||||
relationTo: 'users'
|
relationTo: 'users';
|
||||||
value: string | User
|
value: string | User;
|
||||||
}
|
};
|
||||||
key?: string | null
|
key?: string | null;
|
||||||
value?:
|
value?:
|
||||||
| {
|
| {
|
||||||
[k: string]: unknown
|
[k: string]: unknown;
|
||||||
}
|
}
|
||||||
| unknown[]
|
| unknown[]
|
||||||
| string
|
| string
|
||||||
| number
|
| number
|
||||||
| boolean
|
| boolean
|
||||||
| null
|
| null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-migrations".
|
* via the `definition` "payload-migrations".
|
||||||
*/
|
*/
|
||||||
export interface PayloadMigration {
|
export interface PayloadMigration {
|
||||||
id: string
|
id: string;
|
||||||
name?: string | null
|
name?: string | null;
|
||||||
batch?: number | null
|
batch?: number | null;
|
||||||
updatedAt: string
|
updatedAt: string;
|
||||||
createdAt: string
|
createdAt: string;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "menu".
|
* via the `definition` "menu".
|
||||||
*/
|
*/
|
||||||
export interface Menu {
|
export interface Menu {
|
||||||
id: string
|
id: string;
|
||||||
globalText?: string | null
|
globalText?: string | null;
|
||||||
updatedAt?: string | null
|
updatedAt?: string | null;
|
||||||
createdAt?: string | null
|
createdAt?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
declare module 'payload' {
|
declare module 'payload' {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export interface GeneratedTypes extends Config {}
|
export interface GeneratedTypes extends Config {}
|
||||||
}
|
}
|
||||||
@@ -134,6 +134,8 @@ describe('Auth', () => {
|
|||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
|
expect(data.strategy).toBeDefined()
|
||||||
|
expect(typeof data.exp).toBe('number')
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
expect(data.user.email).toBeDefined()
|
expect(data.user.email).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user