Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth: Add TS types for auth method options #7745

Merged
merged 7 commits into from
Mar 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const auth0MockClient: Partial<Auth0Client> = {
loginWithRedirect: async () => {
loggedInUser = user
},
logout: () => {},
logout: async () => {},
getTokenSilently,
getUser: <TUser extends User>() => {
return new Promise<TUser | undefined>((resolve) => {
Expand Down Expand Up @@ -80,7 +80,7 @@ beforeEach(() => {
})

function getAuth0Auth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-providers/auth0/web/src/auth0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface Auth0User {}
export function createAuth(
auth0Client: Auth0Client,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ const defaultToken = () => ({

const azureActiveDirectoryMockClient: Partial<AzureActiveDirectoryClient> = {
loginRedirect: async (options?: RedirectRequest) => {
if (options?.claims?.includes('admin')) {
const claims = JSON.parse(options?.claims || '{}')
if (claims.accessToken?.find((token) => token.name === 'role')) {
loggedInUser = adminUser
} else {
loggedInUser = user
Expand Down Expand Up @@ -115,7 +116,7 @@ beforeEach(() => {
})

function getAzureActiveDirectoryAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down Expand Up @@ -184,7 +185,22 @@ describe('azureActiveDirectoryAuth', () => {
expect(authRef.current.hasRole('admin')).toBeFalsy()

await act(async () => {
authRef.current.logIn({ claims: ['admin'] })
const claimsRequest = {
idToken: [
{ name: 'name', essential: true },
{ name: 'email', essential: true },
{ name: 'country', essential: false },
],
accessToken: [
{ name: 'role', essential: true },
{ name: 'permissions', essential: true },
],
}

authRef.current.logIn({
scopes: ['openid', 'profile'],
claims: JSON.stringify(claimsRequest),
})
})

expect(authRef.current.hasRole('admin')).toBeTruthy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { CurrentUser, createAuthentication } from '@redwoodjs/auth'
export function createAuth(
azureActiveDirectoryClient: AzureActiveDirectoryClient,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ beforeEach(() => {
})

function getClerkAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-providers/clerk/web/src/clerk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CurrentUser, createAuthentication } from '@redwoodjs/auth'
type Clerk = ClerkClient | undefined | null

export function createAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
18 changes: 15 additions & 3 deletions packages/auth-providers/dbAuth/web/src/__tests__/dbAuth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ beforeEach(() => {
})

const defaultArgs: DbAuthClientArgs & {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down Expand Up @@ -189,7 +189,13 @@ describe('dbAuth', () => {

it('passes through fetchOptions to resetPassword calls', async () => {
const auth = getDbAuth().current
await act(async () => await auth.resetPassword({}))
await act(
async () =>
await auth.resetPassword({
resetToken: 'reset-token',
password: 'password',
})
)

expect(globalThis.fetch).toBeCalledWith(
`${globalThis.RWJS_API_URL}/auth`,
Expand All @@ -201,7 +207,13 @@ describe('dbAuth', () => {

it('passes through fetchOptions to signup calls', async () => {
const auth = getDbAuth().current
await act(async () => await auth.signUp({}))
await act(
async () =>
await auth.signUp({
username: 'username',
password: 'password',
})
)

expect(globalThis.fetch).toBeCalledWith(
`${globalThis.RWJS_API_URL}/auth`,
Expand Down
4 changes: 2 additions & 2 deletions packages/auth-providers/dbAuth/web/src/dbAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface LoginAttributes {
}

export interface ResetPasswordAttributes {
token: string
resetToken: string
password: string
}

Expand All @@ -19,7 +19,7 @@ const TOKEN_CACHE_TIME = 5000
export function createAuth(
dbAuthClient: ReturnType<typeof createDbAuthClient>,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ beforeEach(() => {
})

function getFirebaseAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-providers/firebase/web/src/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const applyProviderOptions = (
export function createAuth(
firebaseClient: FirebaseClient,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ beforeEach(() => {
})

function getNetlifyAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
9 changes: 5 additions & 4 deletions packages/auth-providers/netlify/web/src/netlify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type NetlifyIdentity = typeof NetlifyIdentityNS
export function createAuth(
netlifyIdentity: NetlifyIdentity,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand All @@ -32,7 +32,8 @@ function createAuthImplementation(netlifyIdentity: NetlifyIdentity) {
return {
type: 'netlify',
client: netlifyIdentity,
login: () => {
// `_options: never` is needed to help TS infer the TLogInOptions type
login: (_options: never) => {
return new Promise<NetlifyIdentityNS.User | null>((resolve, reject) => {
let autoClosedModal = false
netlifyIdentity.open('login')
Expand All @@ -48,14 +49,14 @@ function createAuthImplementation(netlifyIdentity: NetlifyIdentity) {
netlifyIdentity.on('error', reject)
})
},
logout: () => {
logout: (_options: never) => {
return new Promise<void>((resolve, reject) => {
netlifyIdentity.logout()
netlifyIdentity.on('logout', resolve)
netlifyIdentity.on('error', reject)
})
},
signup: () => {
signup: (_options: never) => {
return new Promise<null>((resolve, reject) => {
netlifyIdentity.open('signup')
netlifyIdentity.on('close', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ beforeEach(() => {
})

function getSupabaseAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-providers/supabase/web/src/supabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export type SignInWithSSOOptions = SignInWithSSO & {
export function createAuth(
supabaseClient: SupabaseClient,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ beforeEach(() => {
})

function getSuperTokensAuth(customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-providers/supertokens/web/src/supertokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type SessionRecipe = {
export function createAuth(
superTokens: SuperTokensAuth,
customProviderHooks?: {
useCurrentUser?: () => Promise<Record<string, unknown>>
useCurrentUser?: () => Promise<CurrentUser>
useHasRole?: (
currentUser: CurrentUser | null
) => (rolesToCheck: string | string[]) => boolean
Expand Down
20 changes: 16 additions & 4 deletions packages/auth/src/AuthContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ export interface CurrentUser {

export interface AuthContextInterface<
TUser,
TLogInOptions,
TLogIn,
TLogOutOptions,
TLogOut,
TSignUpOptions,
TSignUp,
TForgotPassword,
TResetPasswordOptions,
TResetPassword,
TValidateResetToken,
TClient
Expand Down Expand Up @@ -40,9 +44,9 @@ export interface AuthContextInterface<
* ```
*/
userMetadata: null | TUser
logIn(options?: unknown): Promise<TLogIn>
logOut(options?: unknown): Promise<TLogOut>
signUp(options?: unknown): Promise<TSignUp>
logIn(options?: TLogInOptions): Promise<TLogIn>
logOut(options?: TLogOutOptions): Promise<TLogOut>
signUp(options?: TSignUpOptions): Promise<TSignUp>
/**
* Clients should always return null or string
* It is expected that they catch any errors internally
Expand All @@ -65,7 +69,7 @@ export interface AuthContextInterface<
*/
reauthenticate(): Promise<void>
forgotPassword(username: string): Promise<TForgotPassword>
resetPassword(options?: unknown): Promise<TResetPassword>
resetPassword(options?: TResetPasswordOptions): Promise<TResetPassword>
validateResetToken(resetToken: string | null): Promise<TValidateResetToken>
/**
* A reference to auth service provider sdk "client", which is useful if we
Expand All @@ -79,21 +83,29 @@ export interface AuthContextInterface<

export function createAuthContext<
TUser,
TLogInOptions,
TLogIn,
TLogOutOptions,
TLogOut,
TSignUpOptions,
TSignUp,
TForgotPassword,
TResetPasswordOptions,
TResetPassword,
TValidateResetToken,
TClient
>() {
return React.createContext<
| AuthContextInterface<
TUser,
TLogInOptions,
TLogIn,
TLogOutOptions,
TLogOut,
TSignUpOptions,
TSignUp,
TForgotPassword,
TResetPasswordOptions,
TResetPassword,
TValidateResetToken,
TClient
Expand Down
14 changes: 9 additions & 5 deletions packages/auth/src/AuthImplementation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
export interface AuthImplementation<
TUser = unknown,
TRestoreAuth = unknown,
TLogInOptions = unknown,
TLogIn = unknown,
TLogOutOptions = unknown,
TLogOut = unknown,
TSignUpOptions = unknown,
TSignUp = unknown,
TForgotPassword = unknown,
TResetPasswordOptions = unknown,
TResetPassword = unknown,
TValidateResetToken = unknown,
TClient = unknown
Expand All @@ -13,12 +17,12 @@ export interface AuthImplementation<
client?: TClient

restoreAuthState?(): Promise<TRestoreAuth>
login(options?: unknown): Promise<TLogIn>
logout(options?: unknown): Promise<TLogOut>
signup(options?: unknown): Promise<TSignUp>
getToken(options?: unknown): Promise<string | null>
login(options?: TLogInOptions): Promise<TLogIn>
logout(options?: TLogOutOptions): Promise<TLogOut>
signup(options?: TSignUpOptions): Promise<TSignUp>
getToken(): Promise<string | null>
forgotPassword?(username: string): Promise<TForgotPassword>
resetPassword?(options?: unknown): Promise<TResetPassword>
resetPassword?(options?: TResetPasswordOptions): Promise<TResetPassword>
validateResetToken?(token: string | null): Promise<TValidateResetToken>
clientHasLoaded?(): boolean

Expand Down
Loading