diff --git a/.version b/.version index 268fccb1..fbbf144b 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -v5.5.0 +v5.5.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c7a65e..2b6b8529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## [v5.5.1](https://github.com/auth0/react-native-auth0/tree/v5.5.1) (2026-04-23) + +[Full Changelog](https://github.com/auth0/react-native-auth0/compare/v5.5.0...v5.5.1) + +**Fixed** + +- fix: remove conflicting broad scheme from MainActivity to prevent Android disambiguation dialog [\#1514](https://github.com/auth0/react-native-auth0/pull/1514) ([subhankarmaiti](https://github.com/subhankarmaiti)) +- fix: filter universal link callbacks by Auth0 domain in iOS [\#1512](https://github.com/auth0/react-native-auth0/pull/1512) ([subhankarmaiti](https://github.com/subhankarmaiti)) + ## [v5.5.0](https://github.com/auth0/react-native-auth0/tree/v5.5.0) (2026-04-09) [Full Changelog](https://github.com/auth0/react-native-auth0/compare/v5.4.1...v5.5.0) diff --git a/EXAMPLES-WEB.md b/EXAMPLES-WEB.md index 24f7b7ed..21ce8869 100644 --- a/EXAMPLES-WEB.md +++ b/EXAMPLES-WEB.md @@ -158,14 +158,120 @@ const App = () => { }; ``` -## Unsupported Web Features +## 3. MFA Flexible Factors Grant (Web) -For security reasons, the web platform **does not support** direct authentication grants. The following methods from the `auth` provider will throw a `NotImplemented` error: +The MFA Flexible Factors Grant is fully supported on the web platform. It uses the `@auth0/auth0-spa-js` MFA API under the hood. -- `auth.passwordRealm()` -- `auth.loginWithOTP()` -- `auth.loginWithSMS()` -- `auth.loginWithEmail()` -- `auth.refreshToken()` +### Using MFA with Hooks -All these flows should be configured in your [Auth0 Universal Login](https://auth0.com/docs/universal-login) page and initiated via the `authorize()` method. +```tsx +import React, { useState } from 'react'; +import { View, Button, TextInput, Text } from 'react-native'; +import { useAuth0, MfaError, MfaErrorCodes } from 'react-native-auth0'; + +function MfaScreen({ mfaToken }: { mfaToken: string }) { + const { mfa } = useAuth0(); + const [otp, setOtp] = useState(''); + + const listAuthenticators = async () => { + try { + const authenticators = await mfa.getAuthenticators({ mfaToken }); + console.log('Authenticators:', authenticators); + } catch (error) { + if (error instanceof MfaError) { + console.error('MFA error:', error.type, error.message); + } + } + }; + + const enrollTotp = async () => { + try { + const challenge = await mfa.enroll({ mfaToken, type: 'otp' }); + if (challenge.type === 'totp') { + console.log('Scan QR:', challenge.barcodeUri); + console.log('Secret:', challenge.secret); + } + } catch (error) { + if (error instanceof MfaError) { + console.error('Enrollment error:', error.type); + } + } + }; + + const verifyOtp = async () => { + try { + const credentials = await mfa.verify({ mfaToken, otp }); + console.log('Authenticated!', credentials.accessToken); + } catch (error) { + if (error instanceof MfaError) { + switch (error.type) { + case MfaErrorCodes.INVALID_OTP: + console.log('Incorrect code'); + break; + case MfaErrorCodes.TOO_MANY_ATTEMPTS: + console.log('Too many attempts'); + break; + case MfaErrorCodes.EXPIRED_MFA_TOKEN: + console.log('Session expired'); + break; + } + } + } + }; + + return ( + +