Skip to content
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
63 changes: 0 additions & 63 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
- [DPoP](#dpop)
- [Authentication API](#authentication-api)
- [Login with database connection](#login-with-database-connection)
- [Login using MFA with One Time Password code](#login-using-mfa-with-one-time-password-code)
- [MFA Flexible Factors Grant](#mfa-flexible-factors-grant)
- [Understanding the mfa_required Error Payload](#understanding-the-mfa_required-error-payload)
- [Handling MFA Required Errors](#handling-mfa-required-errors)
- [Getting Available Authenticators](#getting-available-authenticators)
- [Enrolling New Authenticators](#enrolling-new-authenticators)
- [Challenging an Authenticator](#challenging-an-authenticator)
- [Verifying MFA](#verifying-mfa)
- [MFA Client Errors](#mfa-client-errors)
- [Passwordless Login](#passwordless-login)
- [Step 1: Request the code](#step-1-request-the-code)
Expand Down Expand Up @@ -52,11 +50,6 @@
- [Handling Credentials Manager exceptions](#handling-credentials-manager-exceptions)
- [Passkeys](#passkeys)
- [Bot Protection](#bot-protection)
- [Management API](#management-api)
- [Link users](#link-users)
- [Unlink users](#unlink-users)
- [Get User Profile](#get-user-profile)
- [Update User Metadata](#update-user-metadata)
- [Token Validation](#token-validation)
- [Organizations](#organizations)
- [Log in to an organization](#log-in-to-an-organization)
Expand Down Expand Up @@ -404,62 +397,6 @@ authentication

> The default scope used is `openid profile email`. Regardless of the scopes set to the request, the `openid` scope is always enforced.

### Login using MFA with One Time Password code

This call requires the client to have the *MFA* Client Grant Type enabled. Check [this article](https://auth0.com/docs/clients/client-grant-types) to learn how to enable it.

When you sign in to a multifactor authentication enabled connection using the `login` method, you receive an error standing that MFA is required for that user along with an `mfa_token` value. Use this value to call `loginWithOTP` and complete the MFA flow passing the One Time Password from the enrolled MFA code generator app.

```kotlin
authentication
.loginWithOTP("the mfa token", "123456")
.validateClaims() //mandatory
.start(object: Callback<Credentials, AuthenticationException> {
override fun onFailure(exception: AuthenticationException) { }

override fun onSuccess(credentials: Credentials) { }
})
```

<details>
<summary>Using coroutines</summary>

```kotlin
try {
val credentials = authentication
.loginWithOTP("the mfa token", "123456")
.validateClaims()
.await()
println(credentials)
} catch (e: AuthenticationException) {
e.printStacktrace()
}
```
</details>

<details>
<summary>Using Java</summary>

```java
authentication
.loginWithOTP("the mfa token", "123456")
.validateClaims() //mandatory
.start(new Callback<Credentials, AuthenticationException>() {
@Override
public void onSuccess(@Nullable Credentials payload) {
//Logged in!
}

@Override
public void onFailure(@NonNull AuthenticationException error) {
//Error!
}
});
```
</details>

> The default scope used is `openid profile email`. Regardless of the scopes set to the request, the `openid` scope is always enforced.

### MFA Flexible Factors Grant

> [!IMPORTANT]
Expand Down
12 changes: 12 additions & 0 deletions V4_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ v4 of the Auth0 Android SDK includes significant build toolchain updates, update
+ [Kotlin Version](#kotlin-version)
- [**Breaking Changes**](#breaking-changes)
+ [Classes Removed](#classes-removed)
+ [Deprecated MFA Methods Removed from AuthenticationAPIClient](#deprecated-mfa-methods-removed-from-authenticationapiclient)
+ [DPoP Configuration Moved to Builder](#dpop-configuration-moved-to-builder)
+ [SSOCredentials.expiresIn Renamed to expiresAt](#ssocredentialsexpiresin-renamed-to-expiresat)
- [**Default Values Changed**](#default-values-changed)
Expand Down Expand Up @@ -110,6 +111,17 @@ buildscript {
2. Call that endpoint from your app, passing the user's access token as a `Bearer` token in the `Authorization` header.
3. On your backend, obtain a machine-to-machine token via the Client Credentials flow and use it to call the Management API with the precise scopes required.

### Deprecated MFA Methods Removed from AuthenticationAPIClient

The following MFA methods have been removed from `AuthenticationAPIClient`. They were deprecated in v3 in favor of the `MfaApiClient` class APIs.

- `loginWithOTP(mfaToken, otp)`
- `loginWithOOB(mfaToken, oobCode, bindingCode)`
- `loginWithRecoveryCode(mfaToken, recoveryCode)`
- `multifactorChallenge(mfaToken, challengeType, authenticatorId)`

Use `AuthenticationAPIClient.mfaClient(mfaToken)` to obtain a `MfaApiClient` instance and handle MFA flows using the new APIs. See the [MFA Flexible Factors Grant](EXAMPLES.md#mfa-flexible-factors-grant) section in `EXAMPLES.md` for usage guidance.

### DPoP Configuration Moved to Builder

The `useDPoP(context: Context)` method has been moved from the `WebAuthProvider` object to the login
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import com.auth0.android.request.internal.GsonAdapter.Companion.forMapOf
import com.auth0.android.request.internal.GsonProvider
import com.auth0.android.request.internal.RequestFactory
import com.auth0.android.request.internal.ResponseUtils.isNetworkError
import com.auth0.android.result.Challenge
import com.auth0.android.result.Credentials
import com.auth0.android.result.DatabaseUser
import com.auth0.android.result.PasskeyChallenge
Expand Down Expand Up @@ -175,42 +174,6 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
}


/**
* Log in a user using the One Time Password code after they have received the 'mfa_required' error.
* The MFA token tells the server the username or email, password, and realm values sent on the first request.
*
* Requires your client to have the **MFA OTP** Grant Type enabled. See [Client Grant Types](https://auth0.com/docs/clients/client-grant-types) to learn how to enable it.
*
* Example usage:
*
*```
* client.loginWithOTP("{mfa token}", "{one time password}")
* .validateClaims() //mandatory
* .start(object : Callback<Credentials, AuthenticationException> {
* override fun onFailure(error: AuthenticationException) { }
* override fun onSuccess(result: Credentials) { }
* })
*```
*
* @param mfaToken the token received in the previous [.login] response.
* @param otp the one time password code provided by the resource owner, typically obtained from an
* MFA application such as Google Authenticator or Guardian.
* @return a request to configure and start that will yield [Credentials]
*/
@Deprecated(
message = "loginWithOTP is deprecated and will be removed in the next major version of the SDK. Use the APIs in the [com.auth0.android.authentication.mfa.MfaApiClient] class instead.",
level = DeprecationLevel.WARNING
)
public fun loginWithOTP(mfaToken: String, otp: String): AuthenticationRequest {
val parameters = ParameterBuilder.newBuilder()
.setGrantType(ParameterBuilder.GRANT_TYPE_MFA_OTP)
.set(MFA_TOKEN_KEY, mfaToken)
.set(ONE_TIME_PASSWORD_KEY, otp)
.asDictionary()
return loginWithToken(parameters)
}


/**
* Sign-in a user using passkeys.
* This should be called after the client has received the passkey challenge from the server and generated the public key response.
Expand Down Expand Up @@ -391,132 +354,6 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
.addParameters(parameters)
}

/**
* Log in a user using an Out Of Band authentication code after they have received the 'mfa_required' error.
* The MFA token tells the server the username or email, password, and realm values sent on the first request.
*
* Requires your client to have the **MFA OOB** Grant Type enabled. See [Client Grant Types](https://auth0.com/docs/clients/client-grant-types) to learn how to enable it.
*
* Example usage:
*
*```
* client.loginWithOOB("{mfa token}", "{out of band code}", "{binding code}")
* .validateClaims() //mandatory
* .start(object : Callback<Credentials, AuthenticationException> {
* override fun onFailure(error: AuthenticationException) { }
* override fun onSuccess(result: Credentials) { }
* })
*```
*
* @param mfaToken the token received in the previous [.login] response.
* @param oobCode the out of band code received in the challenge response.
* @param bindingCode the code used to bind the side channel (used to deliver the challenge) with the main channel you are using to authenticate.
* This is usually an OTP-like code delivered as part of the challenge message.
* @return a request to configure and start that will yield [Credentials]
*/
@Deprecated(
message = "loginWithOOB is deprecated and will be removed in the next major version of the SDK. Use the APIs in the [com.auth0.android.authentication.mfa.MfaApiClient] class instead.",
level = DeprecationLevel.WARNING
)
public fun loginWithOOB(
mfaToken: String,
oobCode: String,
bindingCode: String? = null
): AuthenticationRequest {
val parameters = ParameterBuilder.newBuilder()
.setGrantType(ParameterBuilder.GRANT_TYPE_MFA_OOB)
.set(MFA_TOKEN_KEY, mfaToken)
.set(OUT_OF_BAND_CODE_KEY, oobCode)
.set(BINDING_CODE_KEY, bindingCode)
.asDictionary()
return loginWithToken(parameters)
}

/**
* Log in a user using a multi-factor authentication Recovery Code after they have received the 'mfa_required' error.
* The MFA token tells the server the username or email, password, and realm values sent on the first request.
*
* Requires your client to have the **MFA** Grant Type enabled. See [Client Grant Types](https://auth0.com/docs/clients/client-grant-types) to learn how to enable it.
*
* Example usage:
*
*```
* client.loginWithRecoveryCode("{mfa token}", "{recovery code}")
* .validateClaims() //mandatory
* .start(object : Callback<Credentials, AuthenticationException> {
* override fun onFailure(error: AuthenticationException) { }
* override fun onSuccess(result: Credentials) { }
* })
*```
*
* @param mfaToken the token received in the previous [.login] response.
* @param recoveryCode the recovery code provided by the end-user.
* @return a request to configure and start that will yield [Credentials]. It might also include a [recoveryCode] field,
* which your application must display to the end-user to be stored securely for future use.
*/
@Deprecated(
message = "loginWithRecoveryCode is deprecated and will be removed in the next major version of the SDK. Use the APIs in the [com.auth0.android.authentication.mfa.MfaApiClient] class instead.",
level = DeprecationLevel.WARNING
)
public fun loginWithRecoveryCode(
mfaToken: String,
recoveryCode: String
): AuthenticationRequest {
val parameters = ParameterBuilder.newBuilder()
.setGrantType(ParameterBuilder.GRANT_TYPE_MFA_RECOVERY_CODE)
.set(MFA_TOKEN_KEY, mfaToken)
.set(RECOVERY_CODE_KEY, recoveryCode)
.asDictionary()
return loginWithToken(parameters)
}

/**
* Request a challenge for multi-factor authentication (MFA) based on the challenge types supported by the application and user.
* The challenge type is how the user will get the challenge and prove possession. Supported challenge types include: "otp" and "oob".
*
* Example usage:
*
*```
* client.multifactorChallenge("{mfa token}", "{challenge type}", "{authenticator id}")
* .start(object : Callback<Challenge, AuthenticationException> {
* override fun onFailure(error: AuthenticationException) { }
* override fun onSuccess(result: Challenge) { }
* })
*```
*
* @param mfaToken the token received in the previous [.login] response.
* @param challengeType A whitespace-separated list of the challenges types accepted by your application.
* Accepted challenge types are oob or otp. Excluding this parameter means that your client application
* accepts all supported challenge types.
* @param authenticatorId The ID of the authenticator to challenge.
* @return a request to configure and start that will yield [Challenge]
*/
@Deprecated(
message = "multifactorChallenge is deprecated and will be removed in the next major version of the SDK. Use the APIs in the [com.auth0.android.authentication.mfa.MfaApiClient] class instead.",
level = DeprecationLevel.WARNING
)
public fun multifactorChallenge(
mfaToken: String,
challengeType: String? = null,
authenticatorId: String? = null
): Request<Challenge, AuthenticationException> {
val parameters = ParameterBuilder.newBuilder()
.setClientId(clientId)
.set(MFA_TOKEN_KEY, mfaToken)
.set(CHALLENGE_TYPE_KEY, challengeType)
.set(AUTHENTICATOR_ID_KEY, authenticatorId)
.asDictionary()
val url = auth0.getDomainUrl().toHttpUrl().newBuilder()
.addPathSegment(MFA_PATH)
.addPathSegment(CHALLENGE_PATH)
.build()
val challengeAdapter: JsonAdapter<Challenge> = GsonAdapter(
Challenge::class.java, gson
)
return factory.post(url.toString(), challengeAdapter)
.addParameters(parameters)
}

/**
* Log in a user using a token obtained from a Native Social Identity Provider, such as Facebook, using ['\oauth\token' endpoint](https://auth0.com/docs/api/authentication#token-exchange-for-native-social)
* The default scope used is 'openid profile email'.
Expand Down Expand Up @@ -1128,13 +965,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
private const val OAUTH_CODE_KEY = "code"
private const val REDIRECT_URI_KEY = "redirect_uri"
private const val TOKEN_KEY = "token"
private const val MFA_TOKEN_KEY = "mfa_token"
private const val ONE_TIME_PASSWORD_KEY = "otp"
private const val OUT_OF_BAND_CODE_KEY = "oob_code"
private const val BINDING_CODE_KEY = "binding_code"
private const val CHALLENGE_TYPE_KEY = "challenge_type"
private const val AUTHENTICATOR_ID_KEY = "authenticator_id"
private const val RECOVERY_CODE_KEY = "recovery_code"
private const val SUBJECT_TOKEN_KEY = "subject_token"
private const val SUBJECT_TOKEN_TYPE_KEY = "subject_token_type"
private const val ORGANIZATION_KEY = "organization"
Expand All @@ -1151,7 +982,6 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
private const val TOKEN_PATH = "token"
private const val USER_INFO_PATH = "userinfo"
private const val REVOKE_PATH = "revoke"
private const val MFA_PATH = "mfa"
private const val CHALLENGE_PATH = "challenge"
private const val PASSKEY_PATH = "passkey"
private const val REGISTER_PATH = "register"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.google.gson.annotations.SerializedName
/**
* Multi-factor authentication (MFA) challenge
*
* @see [com.auth0.android.authentication.AuthenticationAPIClient.multifactorChallenge]
* @see [com.auth0.android.authentication.mfa.MfaApiClient]
*/
public class Challenge(
@field:JsonRequired @field:SerializedName("challenge_type")
Expand Down
Loading
Loading