diff --git a/package-lock.json b/package-lock.json index 98b3fbc0f..f970c875c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,6 +51,7 @@ "@babel/preset-react": "^7.0.0", "@cfaester/enzyme-adapter-react-18": "^0.8.0", "@google-cloud/translate": "^9.1.0", + "@types/auth0-js": "^9.21.6", "babel-jest": "^29.3.1", "babel-loader": "8.4.1", "babel-plugin-stylus-compiler": "^1.4.0", @@ -6341,6 +6342,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/auth0-js": { + "version": "9.21.6", + "resolved": "https://registry.npmjs.org/@types/auth0-js/-/auth0-js-9.21.6.tgz", + "integrity": "sha512-wsvfk03WzQDXCbMdX8lQZH2Thh5AQk9SKQcxrBN1EdRkIOgkw9aIixxBpzsTHu/gj0I514BGQv7t5EyZSgVRmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", diff --git a/package.json b/package.json index 43f773bb9..14b99c696 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "url": "git://github.com/auth0/lock" }, "main": "lib/index.js", + "types": "types/index.d.ts", "scripts": { "start": "grunt dev", "prebuild": "grunt dist", @@ -63,6 +64,7 @@ "@babel/preset-react": "^7.0.0", "@cfaester/enzyme-adapter-react-18": "^0.8.0", "@google-cloud/translate": "^9.1.0", + "@types/auth0-js": "^9.21.6", "babel-jest": "^29.3.1", "babel-loader": "8.4.1", "babel-plugin-stylus-compiler": "^1.4.0", diff --git a/types/auth0-lock-tests.ts b/types/auth0-lock-tests.ts new file mode 100644 index 000000000..7bca887e2 --- /dev/null +++ b/types/auth0-lock-tests.ts @@ -0,0 +1,178 @@ +import * as auth0 from "auth0-js"; +import Auth0Lock, { Auth0LockPasswordless } from "auth0-lock"; + +const CLIENT_ID = "YOUR_AUTH0_APP_CLIENTID"; +const DOMAIN = "YOUR_DOMAIN_AT.auth0.com"; + +// Basic instantiation +const lock: Auth0LockStatic = new Auth0Lock(CLIENT_ID, DOMAIN); + +lock.show(); +lock.hide(); +lock.logout(() => {}); + +// checkSession +lock.checkSession({}, function (error: auth0.Auth0Error, authResult: AuthResult | undefined): void { + if (error || !authResult) { + lock.show(); + } else { + lock.getUserInfo(authResult.accessToken, function (error, profile) { + console.log(error, profile); + }); + } +}); + +// show with options +const showOptions: Auth0LockShowOptions = { + allowedConnections: ["twitter", "facebook"], + allowAutocomplete: true, + allowPasswordAutocomplete: false, + allowShowPassword: true, + allowSignUp: true, + allowForgotPassword: false, + auth: { + autoParseHash: true, + params: { state: "foo" }, + redirect: true, + redirectUrl: "some url", + responseType: "token", + sso: true, + }, + initialScreen: "login", + flashMessage: { + type: "error", + text: "an error has occurred", + }, + language: "en", + languageDictionary: { title: "test" }, + rememberLastLogin: false, +}; + +lock.show(showOptions); + +// on / off events +lock.on("authenticated", function (authResult: AuthResult) { + lock.getUserInfo(authResult.accessToken, function (error, profile) { + console.log(error, profile); + }); +}); + +lock.off("authenticated", (authResult) => {}); + +// Theme options +new Auth0Lock(CLIENT_ID, DOMAIN, { + theme: { + authButtons: { + fooProvider: { displayName: "foo" }, + }, + hideMainScreenTitle: false, + labeledSubmitButton: false, + logo: "https://example.com/assets/logo.png", + primaryColor: "green", + }, +}); + +// Auth options +new Auth0Lock(CLIENT_ID, DOMAIN, { + auth: { + autoParseHash: true, + params: { state: "foo" }, + redirect: true, + redirectUrl: "some url", + responseType: "token", + sso: true, + audience: "https://api.example.com", + }, +}); + +// Previously missing options — these are the options added in this release +new Auth0Lock(CLIENT_ID, DOMAIN, { + forceAutoHeight: true, + mobile: true, + disableWarnings: true, + preferConnectionDisplayName: true, + useCustomPasswordlessConnection: true, + emailFirst: true, + connectionResolver: (userInput, context, callback) => { + callback({ name: "my-connection" }); + }, + hooks: { + loggingIn: (context, cb) => { + cb(); + }, + signingUp: (context, cb) => { + cb(); + }, + }, +}); + +// All constructor options +const allOptions: Auth0LockConstructorOptions = { + additionalSignUpFields: [{ name: "address", placeholder: "enter your address" }], + allowedConnections: ["Username-Password-Authentication"], + allowAutocomplete: true, + allowForgotPassword: true, + allowLogin: true, + allowPasswordAutocomplete: false, + allowSignUp: true, + allowShowPassword: true, + assetsUrl: "https://example.com/assets", + autoclose: true, + autofocus: false, + avatar: null, + clientBaseUrl: "http://www.example.com", + closable: true, + configurationBaseUrl: "https://cdn.auth0.com", + connectionResolver: (userInput, context, callback) => { callback({ name: "my-connection" }); }, + container: "myContainer", + defaultADUsernameFromEmailPrefix: false, + defaultDatabaseConnection: "Username-Password-Authentication", + defaultEnterpriseConnection: "my-enterprise", + disableWarnings: false, + emailFirst: false, + flashMessage: { type: "success", text: "Logged in!" }, + forceAutoHeight: false, + forgotPasswordLink: "https://example.com/forgot", + hashCleanup: true, + hooks: { + loggingIn: (context, cb) => { cb(); }, + signingUp: (context, cb) => { cb(); }, + }, + initialScreen: "login", + language: "en", + languageBaseUrl: "http://www.example.com", + languageDictionary: { title: "My App" }, + leeway: 30, + legacySameSiteCookie: false, + loginAfterSignUp: true, + mobile: false, + mustAcceptTerms: false, + popupOptions: { width: 500, height: 600, left: 100, top: 100 }, + preferConnectionDisplayName: false, + prefill: { email: "user@example.com" }, + rememberLastLogin: true, + scrollGlobalMessagesIntoView: true, + showTerms: true, + signUpFieldsStrictValidation: true, + signUpHideUsernameField: false, + signUpLink: "https://example.com/signup", + socialButtonStyle: "big", + theme: { primaryColor: "#ea5323" }, + useCustomPasswordlessConnection: false, + usernameStyle: "username", + _enableImpersonation: false, + _enableIdPInitiatedLogin: false, + _sendTelemetry: true, + _telemetryInfo: { name: "my-sdk", version: "1.0.0", env: { "auth0.js": "9.0.0" } }, + __useTenantInfo: false, +}; + +new Auth0Lock(CLIENT_ID, DOMAIN, allOptions); + +// Passwordless +new Auth0LockPasswordless(CLIENT_ID, DOMAIN); + +new Auth0LockPasswordless(CLIENT_ID, DOMAIN, { + passwordlessMethod: "code", + forceAutoHeight: true, +}); diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 000000000..fee119361 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,282 @@ +/// + +interface Auth0LockAdditionalSignUpFieldOption { + value: string; + label: string; +} + +type Auth0LockAdditionalSignUpFieldOptionsCallback = ( + error: auth0.Auth0Error, + options: Auth0LockAdditionalSignUpFieldOption[], +) => void; + +type Auth0LockAdditionalSignUpFieldOptionsFunction = (callback: Auth0LockAdditionalSignUpFieldOptionsCallback) => void; + +type Auth0LockAdditionalSignUpFieldPrefillCallback = (error: auth0.Auth0Error, prefill: string) => void; + +type Auth0LockAdditionalSignUpFieldPrefillFunction = (callback: Auth0LockAdditionalSignUpFieldPrefillCallback) => void; + +interface Auth0LockAdditionalTextSignUpField { + type?: "text" | undefined; + icon?: string | undefined; + name: string; + options?: Auth0LockAdditionalSignUpFieldOption[] | Auth0LockAdditionalSignUpFieldOptionsFunction | undefined; + placeholder: string; + prefill?: string | Auth0LockAdditionalSignUpFieldPrefillFunction | undefined; + validator?: ((input: string) => { valid: boolean; hint?: string | undefined }) | undefined; + storage?: "root" | undefined; +} + +interface Auth0LockAdditionalSelectSignUpField { + type?: "select" | undefined; + icon?: string | undefined; + name: string; + options?: Auth0LockAdditionalSignUpFieldOption[] | Auth0LockAdditionalSignUpFieldOptionsFunction | undefined; + placeholder: string; + prefill?: string | Auth0LockAdditionalSignUpFieldPrefillFunction | undefined; + validator?: ((input: string) => { valid: boolean; hint?: string | undefined }) | undefined; + storage?: "root" | undefined; +} + +interface Auth0LockAdditionalCheckboxSignUpField { + type?: "checkbox" | undefined; + icon?: string | undefined; + name: string; + placeholder: string; + prefill: "true" | "false"; + validator?: ((input: string) => { valid: boolean; hint?: string | undefined }) | undefined; + storage?: "root" | undefined; +} + +interface Auth0LockAdditionalHiddenSignUpField { + type?: "hidden" | undefined; + name: string; + value: string; + storage?: "root" | undefined; +} + +type Auth0LockAdditionalSignUpField = + | Auth0LockAdditionalSelectSignUpField + | Auth0LockAdditionalTextSignUpField + | Auth0LockAdditionalCheckboxSignUpField + | Auth0LockAdditionalHiddenSignUpField; + +type Auth0LockAvatarUrlCallback = (error: auth0.Auth0Error, url: string) => void; +type Auth0LockAvatarDisplayNameCallback = (error: auth0.Auth0Error, displayName: string) => void; + +interface Auth0LockAvatarOptions { + url: (email: string, callback: Auth0LockAvatarUrlCallback) => void; + displayName: (email: string, callback: Auth0LockAvatarDisplayNameCallback) => void; +} + +interface Auth0LockThemeButton { + displayName: string; + primaryColor?: string | undefined; + foregroundColor?: string | undefined; + icon?: string | undefined; +} + +interface Auth0LockThemeButtonOptions { + [provider: string]: Auth0LockThemeButton; +} + +interface Auth0LockThemeOptions { + authButtons?: Auth0LockThemeButtonOptions | undefined; + hideMainScreenTitle?: boolean | undefined; + labeledSubmitButton?: boolean | undefined; + logo?: string | undefined; + primaryColor?: string | undefined; +} + +// https://auth0.com/docs/libraries/lock/v10/sending-authentication-parameters +interface Auth0LockAuthParamsOptions { + access_token?: any; + connection_scope?: any; + device?: any; + nonce?: any; + protocol?: any; + request_id?: any; + scope?: string | undefined; + state?: string | undefined; + [key: string]: any; // Auth0 rules can use custom params. +} + +interface Auth0LockAuthOptions { + autoParseHash?: boolean | undefined; + params?: Auth0LockAuthParamsOptions | undefined; + redirect?: boolean | undefined; + redirectUrl?: string | undefined; + responseMode?: string | undefined; + responseType?: string | undefined; + sso?: boolean | undefined; + audience?: string | undefined; +} + +interface Auth0LockPopupOptions { + width: number; + height: number; + left: number; + top: number; +} + +// Hooks that can be used to integrate into various procedures within Lock. +// Both hooks receive a context (currently always null) and a callback that +// must be called when the hook is finished. Execution is blocked until cb() is called. +interface Auth0LockHooks { + loggingIn?: ((context: null, cb: () => void) => void) | undefined; + signingUp?: ((context: null, cb: () => void) => void) | undefined; +} + +interface Auth0LockConstructorOptions { + additionalSignUpFields?: Auth0LockAdditionalSignUpField[] | undefined; + allowedConnections?: string[] | undefined; + allowAutocomplete?: boolean | undefined; + allowForgotPassword?: boolean | undefined; + allowLogin?: boolean | undefined; + allowPasswordAutocomplete?: boolean | undefined; + allowSignUp?: boolean | undefined; + allowShowPassword?: boolean | undefined; + assetsUrl?: string | undefined; + auth?: Auth0LockAuthOptions | undefined; + autoclose?: boolean | undefined; + autofocus?: boolean | undefined; + avatar?: Auth0LockAvatarOptions | null | undefined; + clientBaseUrl?: string | undefined; + closable?: boolean | undefined; + configurationBaseUrl?: string | undefined; + connectionResolver?: ((userInput: string, context: any, callback: (connection: any) => void) => void) | undefined; + container?: string | undefined; + defaultADUsernameFromEmailPrefix?: boolean | undefined; + defaultDatabaseConnection?: string | undefined; + defaultEnterpriseConnection?: string | undefined; + disableWarnings?: boolean | undefined; + emailFirst?: boolean | undefined; + flashMessage?: Auth0LockFlashMessageOptions | undefined; + forceAutoHeight?: boolean | undefined; + forgotPasswordLink?: string | undefined; + hashCleanup?: boolean | undefined; + hooks?: Auth0LockHooks | undefined; + initialScreen?: "login" | "signUp" | "forgotPassword" | undefined; + language?: string | undefined; + languageBaseUrl?: string | undefined; + languageDictionary?: any; + leeway?: number | undefined; + legacySameSiteCookie?: boolean | undefined; + loginAfterSignUp?: boolean | undefined; + mobile?: boolean | undefined; + mustAcceptTerms?: boolean | undefined; + popupOptions?: Auth0LockPopupOptions | undefined; + preferConnectionDisplayName?: boolean | undefined; + prefill?: { email?: string | undefined; username?: string | undefined } | undefined; + rememberLastLogin?: boolean | undefined; + scrollGlobalMessagesIntoView?: boolean | undefined; + showTerms?: boolean | undefined; + signUpFieldsStrictValidation?: boolean | undefined; + signUpHideUsernameField?: boolean | undefined; + signUpLink?: string | undefined; + socialButtonStyle?: "big" | "small" | undefined; + theme?: Auth0LockThemeOptions | undefined; + useCustomPasswordlessConnection?: boolean | undefined; + usernameStyle?: "email" | "username" | undefined; + _enableImpersonation?: boolean | undefined; + _enableIdPInitiatedLogin?: boolean | undefined; + _sendTelemetry?: boolean | undefined; + _telemetryInfo?: { name?: string | undefined; version?: string | undefined; env?: Record | undefined } | undefined; + __useTenantInfo?: boolean | undefined; +} + +interface Auth0LockFlashMessageOptions { + type: "success" | "error" | "info"; + text: string; +} + +interface Auth0LockShowOptions { + allowedConnections?: string[] | undefined; + allowAutocomplete?: boolean | undefined; + allowForgotPassword?: boolean | undefined; + allowLogin?: boolean | undefined; + allowPasswordAutocomplete?: boolean | undefined; + allowShowPassword?: boolean | undefined; + allowSignUp?: boolean | undefined; + auth?: Auth0LockAuthOptions | undefined; + initialScreen?: "login" | "signUp" | "forgotPassword" | undefined; + flashMessage?: Auth0LockFlashMessageOptions | undefined; + language?: string | undefined; + languageDictionary?: any; + rememberLastLogin?: boolean | undefined; +} + +interface Auth0IdTokenPayload { + name?: string | undefined; + nickname?: string | undefined; + picture?: string | undefined; + email?: string | undefined; + email_verified?: boolean | undefined; + aud: string; + exp: number; + iat: number; + iss: string; + sub: string; + acr?: string | undefined; + amr?: string[] | undefined; + [key: string]: any; +} + +interface AuthResult { + accessToken: string; + appState?: any; + expiresIn: number; + idToken: string; + idTokenPayload: Auth0IdTokenPayload; + refreshToken?: string | undefined; + scope?: string | undefined; + state: string; + tokenType: string; +} + +interface Auth0LockCore { + // deprecated + getProfile(token: string, callback: (error: auth0.Auth0Error, profile: auth0.Auth0UserProfile) => void): void; + getUserInfo(token: string, callback: (error: auth0.Auth0Error, profile: auth0.Auth0UserProfile) => void): void; + checkSession( + options: Auth0LockAuthParamsOptions, + callback: (error: auth0.Auth0Error, authResult: AuthResult | undefined) => void, + ): void; + resumeAuth(hash: string, callback: (error: auth0.Auth0Error, authResult: AuthResult) => void): void; + show(options?: Auth0LockShowOptions): void; + hide(): void; + logout(query: any): void; + + on(event: "show" | "hide", callback: () => void): void; + on(event: "unrecoverable_error" | "authorization_error", callback: (error: auth0.Auth0Error) => void): void; + on(event: "authenticated", callback: (authResult: AuthResult) => void): void; + on(event: string, callback: (...args: any[]) => void): void; + + off(event: "show" | "hide", callback: () => void): void; + off(event: "unrecoverable_error" | "authorization_error", callback: (error: auth0.Auth0Error) => void): void; + off(event: "authenticated", callback: (authResult: AuthResult) => void): void; + off(event: string, callback: (...args: any[]) => void): void; +} + +interface Auth0LockStatic extends Auth0LockCore { + new(clientId: string, domain: string, options?: Auth0LockConstructorOptions): Auth0LockStatic; +} + +// additional options for passwordless mode +interface Auth0LockPasswordlessConstructorOptions extends Auth0LockConstructorOptions { + passwordlessMethod?: "code" | "link" | undefined; +} + +interface Auth0LockPasswordlessStatic extends Auth0LockCore { + new( + clientId: string, + domain: string, + options?: Auth0LockPasswordlessConstructorOptions, + ): Auth0LockPasswordlessStatic; +} + +declare module "auth0-lock" { + export default Auth0Lock; + export const Auth0Lock: Auth0LockStatic; + export const Auth0LockPasswordless: Auth0LockPasswordlessStatic; +} diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 000000000..f457703f1 --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6", "dom"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "noEmit": true, + "skipLibCheck": true, + "baseUrl": "..", + "paths": { + "auth0-lock": ["types/index.d.ts"] + } + }, + "files": [ + "index.d.ts", + "auth0-lock-tests.ts" + ] +}