Skip to content

Commit

Permalink
feat(astro,clerk-react,types,vue): expose sessionClaims from `useAu…
Browse files Browse the repository at this point in the history
…th` hook
  • Loading branch information
ijxy committed Dec 20, 2024
1 parent 3256148 commit d339f4d
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 31 deletions.
8 changes: 8 additions & 0 deletions .changeset/honest-oranges-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@clerk/astro': patch
'@clerk/clerk-react': patch
'@clerk/types': patch
'@clerk/vue': patch
---

Expose `sessionClaims` from `useAuth` hooks
10 changes: 7 additions & 3 deletions packages/astro/src/react/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type UseAuth = () => UseAuthReturn;
* }
*/
export const useAuth: UseAuth = () => {
const { sessionId, userId, actor, orgId, orgRole, orgSlug, orgPermissions } = useStore($authStore);
const { sessionId, sessionClaims, userId, actor, orgId, orgRole, orgSlug, orgPermissions } = useStore($authStore);

const getToken: GetToken = useCallback(createGetToken(), []);
const signOut: SignOut = useCallback(createSignOut(), []);
Expand Down Expand Up @@ -113,6 +113,7 @@ export const useAuth: UseAuth = () => {
isLoaded: false,
isSignedIn: undefined,
sessionId,
sessionClaims: undefined,
userId,
actor: undefined,
orgId: undefined,
Expand All @@ -129,6 +130,7 @@ export const useAuth: UseAuth = () => {
isLoaded: true,
isSignedIn: false,
sessionId,
sessionClaims: null,
userId,
actor: null,
orgId: null,
Expand All @@ -140,11 +142,12 @@ export const useAuth: UseAuth = () => {
};
}

if (!!sessionId && !!userId && !!orgId && !!orgRole) {
if (!!sessionId && !!sessionClaims && !!userId && !!orgId && !!orgRole) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId,
Expand All @@ -156,11 +159,12 @@ export const useAuth: UseAuth = () => {
};
}

if (!!sessionId && !!userId && !orgId) {
if (!!sessionId && !!sessionClaims && !!userId && !orgId) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId: null,
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/contexts/AuthContext.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createContextAndHook } from '@clerk/shared/react';
import type { ActJWTClaim, OrganizationCustomPermissionKey, OrganizationCustomRoleKey } from '@clerk/types';
import type { ActJWTClaim, JwtPayload, OrganizationCustomPermissionKey, OrganizationCustomRoleKey } from '@clerk/types';

export type AuthContextValue = {
userId: string | null | undefined;
sessionId: string | null | undefined;
sessionClaims: JwtPayload | null | undefined;
actor: ActJWTClaim | null | undefined;
orgId: string | null | undefined;
orgRole: OrganizationCustomRoleKey | null | undefined;
Expand Down
60 changes: 41 additions & 19 deletions packages/react/src/hooks/__tests__/useAuth.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createCheckAuthorization } from '@clerk/shared/authorization';
import { ClerkInstanceContext } from '@clerk/shared/react';
import type { LoadedClerk } from '@clerk/types';
import type { LoadedClerk, UseAuthReturn } from '@clerk/types';
import { render, renderHook } from '@testing-library/react';
import React from 'react';
import { afterAll, beforeAll, beforeEach, describe, expect, it, test, vi } from 'vitest';
Expand All @@ -24,6 +24,21 @@ vi.mock('../../errors/errorThrower', () => ({
},
}));

const stubSessionClaims = (input: {
sessionId: string;
userId: string;
orgId?: string;
}): NonNullable<UseAuthReturn['sessionClaims']> => ({
__raw: '',
exp: 1,
iat: 1,
iss: '',
nbf: 1,
sid: input.sessionId,
sub: input.userId,
org_id: input.orgId,
});

const TestComponent = () => {
const { isLoaded, isSignedIn } = useAuth();
return (
Expand Down Expand Up @@ -77,6 +92,7 @@ describe('useDerivedAuth', () => {
expect(current.isLoaded).toBe(false);
expect(current.isSignedIn).toBeUndefined();
expect(current.sessionId).toBeUndefined();
expect(current.sessionClaims).toBeUndefined();
expect(current.userId).toBeUndefined();
expect(current.actor).toBeUndefined();
expect(current.orgId).toBeUndefined();
Expand All @@ -92,6 +108,7 @@ describe('useDerivedAuth', () => {
expect(current.isLoaded).toBe(true);
expect(current.isSignedIn).toBe(false);
expect(current.sessionId).toBeNull();
expect(current.sessionClaims).toBeNull();
expect(current.userId).toBeNull();
expect(current.actor).toBeNull();
expect(current.orgId).toBeNull();
Expand All @@ -104,27 +121,29 @@ describe('useDerivedAuth', () => {
it('returns signed in with org context when sessionId, userId, orgId, and orgRole are present', () => {
const authObject = {
sessionId: 'session123',
sessionClaims: stubSessionClaims({ sessionId: 'session123', userId: 'user123' }),
userId: 'user123',
actor: 'actor123',
actor: { sub: 'actor123' },
orgId: 'org123',
orgRole: 'admin',
orgSlug: 'my-org',
signOut: vi.fn(),
getToken: vi.fn(),
};
} satisfies Partial<UseAuthReturn>;

const {
result: { current },
} = renderHook(() => useDerivedAuth(authObject));

expect(current.isLoaded).toBe(true);
expect(current.isSignedIn).toBe(true);
expect(current.sessionId).toBe('session123');
expect(current.userId).toBe('user123');
expect(current.actor).toBe('actor123');
expect(current.orgId).toBe('org123');
expect(current.orgRole).toBe('admin');
expect(current.orgSlug).toBe('my-org');
expect(current.sessionId).toBe(authObject.sessionId);
expect(current.userId).toBe(authObject.userId);
expect(current.sessionClaims).toBe(authObject.sessionClaims);
expect(current.actor?.sub).toBe(authObject.actor.sub);
expect(current.orgId).toBe(authObject.orgId);
expect(current.orgRole).toBe(authObject.orgRole);
expect(current.orgSlug).toBe(authObject.orgSlug);
expect(typeof current.has).toBe('function');
expect(current.signOut).toBe(authObject.signOut);
expect(current.getToken).toBe(authObject.getToken);
Expand All @@ -136,21 +155,23 @@ describe('useDerivedAuth', () => {

it('returns signed in without org context when sessionId and userId are present but no orgId', () => {
const authObject = {
sessionId: 'session123',
userId: 'user123',
actor: 'actor123',
sessionId: 'session123',
sessionClaims: stubSessionClaims({ sessionId: 'session123', userId: 'user123' }),
actor: { sub: 'actor123' },
signOut: vi.fn(),
getToken: vi.fn(),
};
} satisfies Partial<UseAuthReturn>;
const {
result: { current },
} = renderHook(() => useDerivedAuth(authObject));

expect(current.isLoaded).toBe(true);
expect(current.isSignedIn).toBe(true);
expect(current.sessionId).toBe('session123');
expect(current.userId).toBe('user123');
expect(current.actor).toBe('actor123');
expect(current.sessionId).toBe(authObject.sessionId);
expect(current.userId).toBe(authObject.userId);
expect(current.sessionClaims).toBe(authObject.sessionClaims);
expect(current.actor?.sub).toBe(authObject.actor.sub);
expect(current.orgId).toBeNull();
expect(current.orgRole).toBeNull();
expect(current.orgSlug).toBeNull();
Expand All @@ -165,9 +186,9 @@ describe('useDerivedAuth', () => {

it('throws invalid state error if none of the conditions match', () => {
const authObject = {
sessionId: true,
userId: undefined,
};
sessionId: 'session123',
} satisfies Partial<UseAuthReturn>;
renderHook(() => useDerivedAuth(authObject));

// eslint-disable-next-line @typescript-eslint/unbound-method
Expand All @@ -177,10 +198,11 @@ describe('useDerivedAuth', () => {
it('uses provided has function if available', () => {
const mockHas = vi.fn().mockReturnValue('mocked-result');
const authObject = {
sessionId: 'session123',
userId: 'user123',
sessionId: 'session123',
sessionClaims: stubSessionClaims({ sessionId: 'session123', userId: 'user123' }),
has: mockHas,
};
} satisfies Partial<UseAuthReturn>;
const {
result: { current },
} = renderHook(() => useDerivedAuth(authObject));
Expand Down
13 changes: 10 additions & 3 deletions packages/react/src/hooks/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ export const useAuth: UseAuth = (initialAuthState = {}) => {
authContext = initialAuthState != null ? initialAuthState : {};
}

const { sessionId, userId, actor, orgId, orgRole, orgSlug, orgPermissions, factorVerificationAge } = authContext;
const { sessionId, sessionClaims, userId, actor, orgId, orgRole, orgSlug, orgPermissions, factorVerificationAge } =
authContext;
const isomorphicClerk = useIsomorphicClerkContext();

const getToken: GetToken = useCallback(createGetToken(isomorphicClerk), [isomorphicClerk]);
const signOut: SignOut = useCallback(createSignOut(isomorphicClerk), [isomorphicClerk]);

return useDerivedAuth({
sessionId,
sessionClaims,
userId,
actor,
orgId,
Expand Down Expand Up @@ -106,6 +108,7 @@ export const useAuth: UseAuth = (initialAuthState = {}) => {
export function useDerivedAuth(authObject: any): UseAuthReturn {
const {
sessionId,
sessionClaims,
userId,
actor,
orgId,
Expand Down Expand Up @@ -139,6 +142,7 @@ export function useDerivedAuth(authObject: any): UseAuthReturn {
isLoaded: false,
isSignedIn: undefined,
sessionId,
sessionClaims: undefined,
userId,
actor: undefined,
orgId: undefined,
Expand All @@ -155,6 +159,7 @@ export function useDerivedAuth(authObject: any): UseAuthReturn {
isLoaded: true,
isSignedIn: false,
sessionId,
sessionClaims: null,
userId,
actor: null,
orgId: null,
Expand All @@ -166,11 +171,12 @@ export function useDerivedAuth(authObject: any): UseAuthReturn {
};
}

if (!!sessionId && !!userId && !!orgId && !!orgRole) {
if (!!sessionId && !!sessionClaims && !!userId && !!orgId && !!orgRole) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId,
Expand All @@ -182,11 +188,12 @@ export function useDerivedAuth(authObject: any): UseAuthReturn {
};
}

if (!!sessionId && !!userId && !orgId) {
if (!!sessionId && !!sessionClaims && !!userId && !orgId) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId: null,
Expand Down
5 changes: 5 additions & 0 deletions packages/types/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { SignInResource } from 'signIn';

import type { SetActive, SignOut } from './clerk';
import type { ActJWTClaim } from './jwt';
import type { JwtPayload } from './jwtv2';
import type {
ActiveSessionResource,
CheckAuthorizationWithCustomPermissions,
Expand All @@ -21,6 +22,7 @@ export type UseAuthReturn =
isSignedIn: undefined;
userId: undefined;
sessionId: undefined;
sessionClaims: undefined;
actor: undefined;
orgId: undefined;
orgRole: undefined;
Expand All @@ -34,6 +36,7 @@ export type UseAuthReturn =
isSignedIn: false;
userId: null;
sessionId: null;
sessionClaims: null;
actor: null;
orgId: null;
orgRole: null;
Expand All @@ -47,6 +50,7 @@ export type UseAuthReturn =
isSignedIn: true;
userId: string;
sessionId: string;
sessionClaims: JwtPayload;
actor: ActJWTClaim | null;
orgId: null;
orgRole: null;
Expand All @@ -60,6 +64,7 @@ export type UseAuthReturn =
isSignedIn: true;
userId: string;
sessionId: string;
sessionClaims: JwtPayload;
actor: ActJWTClaim | null;
orgId: string;
orgRole: OrganizationCustomRoleKey;
Expand Down
10 changes: 7 additions & 3 deletions packages/vue/src/composables/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const useAuth: UseAuth = () => {
const { clerk, authCtx } = useClerkContext();

const result = computed<UseAuthReturn>(() => {
const { sessionId, userId, actor, orgId, orgRole, orgSlug, orgPermissions } = authCtx.value;
const { sessionId, sessionClaims, userId, actor, orgId, orgRole, orgSlug, orgPermissions } = authCtx.value;

const getToken: GetToken = createGetToken(clerk);
const signOut: SignOut = createSignOut(clerk);
Expand Down Expand Up @@ -103,6 +103,7 @@ export const useAuth: UseAuth = () => {
isLoaded: false,
isSignedIn: undefined,
sessionId,
sessionClaims: undefined,
userId,
actor: undefined,
orgId: undefined,
Expand All @@ -119,6 +120,7 @@ export const useAuth: UseAuth = () => {
isLoaded: true,
isSignedIn: false,
sessionId,
sessionClaims: null,
userId,
actor: null,
orgId: null,
Expand All @@ -130,11 +132,12 @@ export const useAuth: UseAuth = () => {
};
}

if (!!sessionId && !!userId && !!orgId && !!orgRole) {
if (!!sessionId && !!sessionClaims && !!userId && !!orgId && !!orgRole) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId,
Expand All @@ -146,11 +149,12 @@ export const useAuth: UseAuth = () => {
};
}

if (!!sessionId && !!userId && !orgId) {
if (!!sessionId && !!sessionClaims && !!userId && !orgId) {
return {
isLoaded: true,
isSignedIn: true,
sessionId,
sessionClaims,
userId,
actor: actor || null,
orgId: null,
Expand Down
4 changes: 2 additions & 2 deletions packages/vue/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ export const clerkPlugin: Plugin = {
const derivedState = computed(() => deriveState(loaded.value, resources.value, initialState));

const authCtx = computed(() => {
const { sessionId, userId, orgId, actor, orgRole, orgSlug, orgPermissions } = derivedState.value;
return { sessionId, userId, actor, orgId, orgRole, orgSlug, orgPermissions };
const { sessionId, sessionClaims, userId, orgId, actor, orgRole, orgSlug, orgPermissions } = derivedState.value;
return { sessionId, sessionClaims, userId, actor, orgId, orgRole, orgSlug, orgPermissions };
});
const clientCtx = computed(() => resources.value.client);
const userCtx = computed(() => derivedState.value.user);
Expand Down
Loading

0 comments on commit d339f4d

Please sign in to comment.