UNPKG

@saleor/sdk

Version:
516 lines (477 loc) 14.6 kB
import { CHANGE_USER_PASSWORD, EXTERNAL_AUTHENTICATION_URL, EXTERNAL_LOGOUT, EXTERNAL_REFRESH, EXTERNAL_REFRESH_WITH_USER, EXTERNAL_VERIFY_TOKEN, LOGIN, LOGIN_WITHOUT_DETAILS, OBTAIN_EXTERNAL_ACCESS_TOKEN, REFRESH_TOKEN, REFRESH_TOKEN_WITH_USER, REGISTER, REQUEST_PASSWORD_RESET, SET_PASSWORD, VERIFY_TOKEN, } from "../apollo/mutations"; import { USER, USER_WITHOUT_DETAILS } from "../apollo/queries"; import { ExternalAuthenticationUrlMutation, ExternalAuthenticationUrlMutationVariables, ExternalLogoutMutation, ExternalLogoutMutationVariables, ExternalObtainAccessTokensMutation, ExternalObtainAccessTokensMutationVariables, ExternalRefreshMutation, ExternalRefreshMutationVariables, ExternalRefreshWithUserMutation, ExternalRefreshWithUserMutationVariables, ExternalVerifyMutation, ExternalVerifyMutationVariables, LoginMutation, LoginMutationVariables, PasswordChangeMutation, PasswordChangeMutationVariables, RefreshTokenMutation, RefreshTokenMutationVariables, RefreshTokenWithUserMutation, RefreshTokenWithUserMutationVariables, RegisterMutation, RegisterMutationVariables, RequestPasswordResetMutation, RequestPasswordResetMutationVariables, SetPasswordMutation, SetPasswordMutationVariables, VerifyTokenMutation, VerifyTokenMutationVariables, } from "../apollo/types"; import { hasNonEmptyPermissions } from "./helpers"; import { storage } from "./storage"; import { ChangePasswordOpts, ChangePasswordResult, GetExternalAccessTokenOpts, GetExternalAccessTokenResult, GetExternalAuthUrlOpts, GetExternalAuthUrlResult, LoginOpts, LoginResult, LogoutOpts, LogoutResult, RefreshExternalTokenResult, RefreshTokenResult, RegisterOpts, RegisterResult, RequestPasswordResetOpts, RequestPasswordResetResult, SaleorClientMethodsProps, SetPasswordOpts, SetPasswordResult, VerifyExternalTokenResult, VerifyTokenResult, } from "./types"; export interface AuthSDK { /** * Change the password of the logged in user. * * @param opts - Object with password and new password. * @returns Errors if the passoword change has failed. */ changePassword: (opts: ChangePasswordOpts) => Promise<ChangePasswordResult>; /** * Authenticates user with email and password. * * @param opts - Object with user's email, password and a boolean includeDetails - whether to fetch user details. * Default for includeDetails is true. * @returns Promise resolved with CreateToken type data. */ login: (opts: LoginOpts) => Promise<LoginResult>; /** * Clears stored token and Apollo store. If external plugin was used to log in, the mutation will prepare * the logout URL. All values passed in field input will be added as GET parameters to the logout request. * * @param opts - Object with input as JSON with returnTo - the URL where a user should be redirected * when external plugin was used to log in * @returns Logout data and errors if external plugin was used to log in. Otherwise null. */ logout: (opts?: LogoutOpts) => Promise<LogoutResult>; /** * Refresh JWT token. Mutation will try to take refreshToken from the function's arguments. * If it fails, it will try to use refreshToken from the http-only cookie called refreshToken. * * @param includeUser - Whether to fetch user. Default false. * @returns Authorization token. */ refreshToken: (includeUser?: boolean) => Promise<RefreshTokenResult>; /** * Registers user with email and password. * * @param opts - Object with user's data. Email and password are required fields. * "channel" can be changed by using first "setChannel" method from api. * @returns Promise resolved with AccountRegister type data. */ register: (opts: RegisterOpts) => Promise<RegisterResult>; /** * Sends an email with the account password modification link. * * @param opts - Object with slug of a channel which will be used for notify user, * email of the user that will be used for password recovery and URL of a view * where users should be redirected to reset the password. URL in RFC 1808 format. * * @returns Errors if there were some. */ requestPasswordReset: ( opts: RequestPasswordResetOpts ) => Promise<RequestPasswordResetResult>; /** * Sets the user's password from the token sent by email. * * @param opts - Object with user's email, password and one-time token required to set the password. * @returns User instance, JWT token, JWT refresh token and CSRF token. */ setPassword: (opts: SetPasswordOpts) => Promise<SetPasswordResult>; /** * Verify JWT token. * * @param token - Token value. * @returns User assigned to token and the information if the token is valid or not. */ verifyToken: () => Promise<VerifyTokenResult>; /** * Executing externalAuthenticationUrl mutation will prepare special URL which will redirect user to requested * page after successfull authentication. After redirection state and code fields will be added to the URL. * * @param opts - Object withpluginId default value set as "mirumee.authentication.openidconnect" and input as * JSON with redirectUrl - the URL where the user should be redirected after successful authentication. * @returns Authentication data and errors */ getExternalAuthUrl: ( opts: GetExternalAuthUrlOpts ) => Promise<GetExternalAuthUrlResult>; /** * The externalObtainAccessTokens mutation will generate requested access tokens. * * @param opts - Object withpluginId default value set as "mirumee.authentication.openidconnect" and input as * JSON with code - the authorization code received from the OAuth provider and state - the state value received * from the OAuth provider * @returns Login authentication data and errors */ getExternalAccessToken: ( opts: GetExternalAccessTokenOpts ) => Promise<GetExternalAccessTokenResult>; /** * The externalRefresh mutation will generate new access tokens when provided with a valid refresh token. * * @param includeUser - Whether to fetch user. Default false. * @returns Token refresh data and errors */ refreshExternalToken: ( includeUser?: boolean ) => Promise<RefreshExternalTokenResult>; /** * The mutation will verify the authentication token. * * @returns Token verification data and errors */ verifyExternalToken: () => Promise<VerifyExternalTokenResult>; } export const auth = ({ apolloClient: client, channel, }: SaleorClientMethodsProps): AuthSDK => { const login: AuthSDK["login"] = ({ includeDetails = true, ...opts }) => { const query = includeDetails ? USER : USER_WITHOUT_DETAILS; const loginMutation = includeDetails ? LOGIN : LOGIN_WITHOUT_DETAILS; client.writeQuery({ query, data: { authenticating: true, }, }); return client.mutate<LoginMutation, LoginMutationVariables>({ mutation: loginMutation, variables: { ...opts, }, update: (_, { data }) => { if (data?.tokenCreate?.token) { storage.setTokens({ accessToken: data.tokenCreate.token, refreshToken: data.tokenCreate.refreshToken, }); } else { client.writeQuery({ query, data: { authenticating: false, }, }); } }, }); }; const logout: AuthSDK["logout"] = async opts => { const authPluginId = storage.getAuthPluginId(); storage.clear(); client.writeQuery({ query: USER, data: { authenticating: false, }, }); client.resetStore(); if (authPluginId && opts?.input) { const result = await client.mutate< ExternalLogoutMutation, ExternalLogoutMutationVariables >({ mutation: EXTERNAL_LOGOUT, variables: { ...opts, pluginId: authPluginId, }, }); return result; } return null; }; const register: AuthSDK["register"] = async opts => await client.mutate<RegisterMutation, RegisterMutationVariables>({ mutation: REGISTER, variables: { input: { ...opts, channel, }, }, }); const refreshToken: AuthSDK["refreshToken"] = (includeUser = false) => { const refreshToken = storage.getRefreshToken(); if (!refreshToken) { throw Error("refreshToken not present"); } if (includeUser) { return client.mutate< RefreshTokenWithUserMutation, RefreshTokenWithUserMutationVariables >({ mutation: REFRESH_TOKEN_WITH_USER, variables: { refreshToken, }, update: (_, { data }) => { if (data?.tokenRefresh?.token) { storage.setAccessToken(data.tokenRefresh.token); } else { logout(); } }, }); } return client.mutate<RefreshTokenMutation, RefreshTokenMutationVariables>({ mutation: REFRESH_TOKEN, variables: { refreshToken, }, update: (_, { data }) => { if (data?.tokenRefresh?.token) { storage.setAccessToken(data.tokenRefresh.token); } else { logout(); } }, }); }; const verifyToken: AuthSDK["verifyToken"] = async () => { const token = storage.getAccessToken(); if (!token) { throw Error("Token not present"); } const result = await client.mutate< VerifyTokenMutation, VerifyTokenMutationVariables >({ mutation: VERIFY_TOKEN, variables: { token }, }); if (!result.data?.tokenVerify?.isValid) { logout(); } return result; }; const changePassword: AuthSDK["changePassword"] = async opts => { const result = await client.mutate< PasswordChangeMutation, PasswordChangeMutationVariables >({ mutation: CHANGE_USER_PASSWORD, variables: { ...opts }, }); return result; }; const requestPasswordReset: AuthSDK["requestPasswordReset"] = async opts => { const result = await client.mutate< RequestPasswordResetMutation, RequestPasswordResetMutationVariables >({ mutation: REQUEST_PASSWORD_RESET, variables: { ...opts, channel }, }); return result; }; const setPassword: AuthSDK["setPassword"] = opts => { return client.mutate<SetPasswordMutation, SetPasswordMutationVariables>({ mutation: SET_PASSWORD, variables: { ...opts }, update: (_, { data }) => { if (data?.setPassword?.token) { storage.setTokens({ accessToken: data.setPassword.token, refreshToken: data.setPassword.refreshToken, }); } }, }); }; const getExternalAuthUrl: AuthSDK["getExternalAuthUrl"] = async opts => { const result = await client.mutate< ExternalAuthenticationUrlMutation, ExternalAuthenticationUrlMutationVariables >({ mutation: EXTERNAL_AUTHENTICATION_URL, variables: { ...opts }, }); return result; }; const getExternalAccessToken: AuthSDK["getExternalAccessToken"] = opts => { client.writeQuery({ query: USER, data: { authenticating: true, }, }); return client.mutate< ExternalObtainAccessTokensMutation, ExternalObtainAccessTokensMutationVariables >({ mutation: OBTAIN_EXTERNAL_ACCESS_TOKEN, variables: { ...opts, }, update: (_, { data }) => { storage.setAuthPluginId(opts.pluginId); if ( data?.externalObtainAccessTokens?.token && hasNonEmptyPermissions( data?.externalObtainAccessTokens?.user?.userPermissions ) ) { storage.setTokens({ accessToken: data.externalObtainAccessTokens.token, refreshToken: data.externalObtainAccessTokens.refreshToken, }); } else { client.writeQuery({ query: USER, data: { authenticating: false, }, }); } }, }); }; const refreshExternalToken: AuthSDK["refreshExternalToken"] = ( includeUser = false ) => { const refreshToken = storage.getRefreshToken(); const authPluginId = storage.getAuthPluginId(); if (!refreshToken) { throw Error("refreshToken not present"); } if (includeUser) { return client.mutate< ExternalRefreshWithUserMutation, ExternalRefreshWithUserMutationVariables >({ mutation: EXTERNAL_REFRESH_WITH_USER, variables: { pluginId: authPluginId, input: JSON.stringify({ refreshToken, }), }, update: (_, { data }) => { if (data?.externalRefresh?.token) { storage.setTokens({ accessToken: data.externalRefresh.token, refreshToken: data.externalRefresh.refreshToken, }); } else { logout(); } }, }); } return client.mutate< ExternalRefreshMutation, ExternalRefreshMutationVariables >({ mutation: EXTERNAL_REFRESH, variables: { pluginId: authPluginId, input: JSON.stringify({ refreshToken, }), }, update: (_, { data }) => { if (data?.externalRefresh?.token) { storage.setTokens({ accessToken: data.externalRefresh.token, refreshToken: data.externalRefresh.refreshToken, }); } else { logout(); } }, }); }; const verifyExternalToken: AuthSDK["verifyExternalToken"] = async () => { const refreshToken = storage.getRefreshToken(); const authPluginId = storage.getAuthPluginId(); if (!refreshToken) { throw Error("refreshToken not present"); } const result = await client.mutate< ExternalVerifyMutation, ExternalVerifyMutationVariables >({ mutation: EXTERNAL_VERIFY_TOKEN, variables: { pluginId: authPluginId, input: JSON.stringify({ refreshToken, }), }, }); if (!result.data?.externalVerify?.isValid) { storage.clear(); } return result; }; return { changePassword, getExternalAccessToken, getExternalAuthUrl, login, logout, refreshExternalToken, refreshToken, register, requestPasswordReset, setPassword, verifyExternalToken, verifyToken, }; };