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
18 changes: 10 additions & 8 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,8 @@ To sign up a user with passkey
try {
val challenge = authenticationApiClient.signupWithPasskey(
"{user-data}",
"{realm}"
"{realm}",
"{organization-id}"
).await()

//Use CredentialManager to create public key credentials
Expand All @@ -1048,7 +1049,7 @@ try {
)

val userCredential = authenticationApiClient.signinWithPasskey(
challenge.authSession, authRequest, "{realm}"
challenge.authSession, authRequest, "{realm}" , "{organization-id}"
)
.validateClaims()
.await()
Expand All @@ -1060,7 +1061,7 @@ try {
<summary>Using Java</summary>

```java
authenticationAPIClient.signupWithPasskey("{user-data}", "{realm}")
authenticationAPIClient.signupWithPasskey("{user-data}", "{realm}","{organization-id}")
.start(new Callback<PasskeyRegistrationChallenge, AuthenticationException>() {
@Override
public void onSuccess(PasskeyRegistrationChallenge result) {
Expand All @@ -1078,7 +1079,7 @@ try {
PublicKeyCredentials.class);

authenticationAPIClient.signinWithPasskey(result.getAuthSession(),
credentials, "{realm}")
credentials, "{realm}","{organization-id}")
.start(new Callback<Credentials, AuthenticationException>() {
@Override
public void onSuccess(Credentials result) {}
Expand All @@ -1104,7 +1105,7 @@ To sign in a user with passkey
try {

val challenge =
authenticationApiClient.passkeyChallenge("{realm}")
authenticationApiClient.passkeyChallenge("{realm}","{organization-id}")
.await()

//Use CredentialManager to create public key credentials
Expand All @@ -1122,7 +1123,8 @@ try {
val userCredential = authenticationApiClient.signinWithPasskey(
challenge.authSession,
authRequest,
"{realm}"
"{realm}",
"{organization-id}"
)
.validateClaims()
.await()
Expand All @@ -1138,7 +1140,7 @@ try {
<summary>Using Java</summary>

```java
authenticationAPIClient.passkeyChallenge("realm")
authenticationAPIClient.passkeyChallenge("realm","{organization-id}")
.start(new Callback<PasskeyChallenge, AuthenticationException>() {
@Override
public void onSuccess(PasskeyChallenge result) {
Expand All @@ -1158,7 +1160,7 @@ authenticationAPIClient.passkeyChallenge("realm")
responseJson,
PublicKeyCredentials.class
);
authenticationAPIClient.signinWithPasskey(result.getAuthSession(), publicKeyCredentials,"{realm}")
authenticationAPIClient.signinWithPasskey(result.getAuthSession(), publicKeyCredentials,"{realm}","{organization-id}")
.start(new Callback<Credentials, AuthenticationException>() {
@Override
public void onSuccess(Credentials result) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
* Example usage:
*
* ```
* client.signinWithPasskey("{authSession}", "{authResponse}","{realm}")
* client.signinWithPasskey("{authSession}", "{authResponse}","{realm}","${organization}")
* .validateClaims() //mandatory
* .setScope("{scope}")
* .start(object: Callback<Credentials, AuthenticationException> {
Expand All @@ -178,17 +178,20 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
* @param authSession the auth session received from the server as part of the public key challenge request.
* @param authResponse the [PublicKeyCredentials] authentication response
* @param realm the connection to use. If excluded, the application will use the default connection configured in the tenant
* @param organization id of the organization to be associated with the user while signing in
* @return a request to configure and start that will yield [Credentials]
*/
public fun signinWithPasskey(
authSession: String,
authResponse: PublicKeyCredentials,
realm: String? = null
realm: String? = null,
organization: String? = null,
): AuthenticationRequest {
val params = ParameterBuilder.newBuilder().apply {
setGrantType(ParameterBuilder.GRANT_TYPE_PASSKEY)
set(AUTH_SESSION_KEY, authSession)
realm?.let { setRealm(it) }
organization?.let { set(ORGANIZATION_KEY, organization) }
}.asDictionary()

return loginWithToken(params)
Expand All @@ -210,7 +213,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
* Example usage:
*
* ```
* client.signinWithPasskey("{authSession}", "{authResponse}","{realm}")
* client.signinWithPasskey("{authSession}", "{authResponse}","{realm}","{organization}")
* .validateClaims() //mandatory
* .setScope("{scope}")
* .start(object: Callback<Credentials, AuthenticationException> {
Expand All @@ -222,18 +225,20 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
* @param authSession the auth session received from the server as part of the public key challenge request.
* @param authResponse the public key credential authentication response in JSON string format that follows the standard webauthn json format
* @param realm the connection to use. If excluded, the application will use the default connection configured in the tenant
* @param organization id of the organization to be associated with the user while signing in
* @return a request to configure and start that will yield [Credentials]
*/
public fun signinWithPasskey(
authSession: String,
authResponse: String,
realm: String? = null
realm: String? = null,
organization: String? = null,
): AuthenticationRequest {
val publicKeyCredentials = gson.fromJson(
authResponse,
PublicKeyCredentials::class.java
)
return signinWithPasskey(authSession, publicKeyCredentials, realm)
return signinWithPasskey(authSession, publicKeyCredentials, realm, organization)
}


Expand All @@ -247,7 +252,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
*
*
* ```
* client.signupWithPasskey("{userData}","{realm}")
* client.signupWithPasskey("{userData}","{realm}","{organization}")
* .addParameter("scope","scope")
* .start(object: Callback<PasskeyRegistration, AuthenticationException> {
* override fun onSuccess(result: PasskeyRegistration) { }
Expand All @@ -257,11 +262,13 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
*
* @param userData user information of the client
* @param realm the connection to use. If excluded, the application will use the default connection configured in the tenant
* @param organization id of the organization to be associated with the user while signing up
* @return a request to configure and start that will yield [PasskeyRegistrationChallenge]
*/
public fun signupWithPasskey(
userData: UserData,
realm: String? = null
realm: String? = null,
organization: String? = null
): Request<PasskeyRegistrationChallenge, AuthenticationException> {
val user = gson.toJsonTree(userData)
val url = auth0.getDomainUrl().toHttpUrl().newBuilder()
Expand All @@ -272,6 +279,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
val params = ParameterBuilder.newBuilder().apply {
setClientId(clientId)
realm?.let { setRealm(it) }
organization?.let { set(ORGANIZATION_KEY, it) }
}.asDictionary()

val passkeyRegistrationChallengeAdapter: JsonAdapter<PasskeyRegistrationChallenge> =
Expand All @@ -293,18 +301,20 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
* Example usage:
*
* ```
* client.passkeyChallenge("{realm}")
* client.passkeyChallenge("{realm}", "{organization}")
* .start(object: Callback<PasskeyChallenge, AuthenticationException> {
* override fun onSuccess(result: PasskeyChallenge) { }
* override fun onFailure(error: AuthenticationException) { }
* })
* ```
*
* @param realm the connection to use. If excluded, the application will use the default connection configured in the tenant
* @param organization id of the organization to be associated with the user while signing in
* @return a request to configure and start that will yield [PasskeyChallenge]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comments should mention the new argument here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was accidentally missed. Updated the same

*/
public fun passkeyChallenge(
realm: String? = null
realm: String? = null,
organization: String? = null
): Request<PasskeyChallenge, AuthenticationException> {
val url = auth0.getDomainUrl().toHttpUrl().newBuilder()
.addPathSegment(PASSKEY_PATH)
Expand All @@ -314,6 +324,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
val parameters = ParameterBuilder.newBuilder().apply {
setClientId(clientId)
realm?.let { setRealm(it) }
organization?.let { set(ORGANIZATION_KEY, organization) }
}.asDictionary()

val passkeyChallengeAdapter: JsonAdapter<PasskeyChallenge> = GsonAdapter(
Expand Down Expand Up @@ -1054,7 +1065,7 @@ public class AuthenticationAPIClient @VisibleForTesting(otherwise = VisibleForTe
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 REQUESTED_TOKEN_TYPE_KEY = "requested_token_type"
private const val ORGANIZATION_KEY = "organization"
private const val USER_METADATA_KEY = "user_metadata"
private const val AUTH_SESSION_KEY = "auth_session"
private const val AUTH_RESPONSE_KEY = "authn_response"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ public class AuthenticationAPIClientTest {
val callback = MockAuthenticationCallback<Credentials>()
val auth0 = auth0
val client = AuthenticationAPIClient(auth0)
client.signinWithPasskey("auth-session", mock<PublicKeyCredentials>(), MY_CONNECTION)
client.signinWithPasskey("auth-session", mock<PublicKeyCredentials>(), MY_CONNECTION,
"testOrganisation")
.start(callback)
ShadowLooper.idleMainLooper()
assertThat(
Expand All @@ -216,6 +217,7 @@ public class AuthenticationAPIClientTest {
)
assertThat(body, Matchers.hasKey("authn_response"))
assertThat(body, Matchers.hasEntry("auth_session", "auth-session"))
assertThat(body, Matchers.hasEntry("organization", "testOrganisation"))
}

@Test
Expand All @@ -225,7 +227,8 @@ public class AuthenticationAPIClientTest {
val client = AuthenticationAPIClient(auth0)
val registrationResponse = client.signupWithPasskey(
mock(),
MY_CONNECTION
MY_CONNECTION,
"testOrganization"
)
.execute()
val request = mockAPI.takeRequest()
Expand All @@ -238,6 +241,7 @@ public class AuthenticationAPIClientTest {
assertThat(request.path, Matchers.equalTo("/passkey/register"))
assertThat(body, Matchers.hasEntry("client_id", CLIENT_ID))
assertThat(body, Matchers.hasEntry("realm", MY_CONNECTION))
assertThat(body, Matchers.hasEntry("organization", "testOrganization"))
assertThat(body, Matchers.hasKey("user_profile"))
assertThat(registrationResponse, Matchers.`is`(Matchers.notNullValue()))
assertThat(registrationResponse.authSession, Matchers.comparesEqualTo(SESSION_ID))
Expand All @@ -248,7 +252,7 @@ public class AuthenticationAPIClientTest {
mockAPI.willReturnSuccessfulPasskeyChallenge()
val auth0 = auth0
val client = AuthenticationAPIClient(auth0)
val challengeResponse = client.passkeyChallenge(MY_CONNECTION)
val challengeResponse = client.passkeyChallenge(MY_CONNECTION, "testOrganization")
.execute()
val request = mockAPI.takeRequest()
assertThat(
Expand All @@ -260,6 +264,7 @@ public class AuthenticationAPIClientTest {
assertThat(request.path, Matchers.equalTo("/passkey/challenge"))
assertThat(body, Matchers.hasEntry("client_id", CLIENT_ID))
assertThat(body, Matchers.hasEntry("realm", MY_CONNECTION))
assertThat(body, Matchers.hasEntry("organization", "testOrganization"))
assertThat(challengeResponse, Matchers.`is`(Matchers.notNullValue()))
assertThat(challengeResponse.authSession, Matchers.comparesEqualTo(SESSION_ID))

Expand Down Expand Up @@ -2749,7 +2754,6 @@ public class AuthenticationAPIClientTest {
private const val FIRST_NAME = "John"
private const val LAST_NAME = "Doe"
private const val COMPANY = "Auth0"
private const val OPENID = "openid"
private const val DEFAULT_LOCALE_IF_MISSING = "en_US"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ public class PasskeyManagerTest {
authenticationAPIClient.signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any()
any(),
eq(null)
)
).thenReturn(
AuthenticationRequestMock(
Expand Down Expand Up @@ -185,7 +186,10 @@ public class PasskeyManagerTest {

verify(authenticationAPIClient).signupWithPasskey(userMetadata, "testRealm")
verify(credentialManager).createCredentialAsync(eq(context), any(), any(), any(), any())
verify(authenticationAPIClient).signinWithPasskey(any(), any<PublicKeyCredentials>(), any())
verify(authenticationAPIClient).signinWithPasskey(
any(), any<PublicKeyCredentials>(), any(),
eq(null)
)
verify(callback).onSuccess(credentialsCaptor.capture())
Assert.assertEquals("codeAccess", credentialsCaptor.firstValue.accessToken)
Assert.assertEquals("codeScope", credentialsCaptor.firstValue.scope)
Expand Down Expand Up @@ -215,7 +219,8 @@ public class PasskeyManagerTest {
verify(authenticationAPIClient, never()).signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any()
any(),
eq(null)
)
verify(credentialManager, never()).createCredentialAsync(
any(),
Expand Down Expand Up @@ -265,7 +270,7 @@ public class PasskeyManagerTest {
verify(authenticationAPIClient, never()).signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any()
any(), eq(null)
)
verify(callback).onFailure(exceptionCaptor.capture())
Assert.assertEquals(
Expand All @@ -292,7 +297,14 @@ public class PasskeyManagerTest {
PublicKeyCredential(registrationResponseJSON)
)

`when`(authenticationAPIClient.signinWithPasskey(any(), any<PublicKeyCredentials>(), any())).thenReturn(
`when`(
authenticationAPIClient.signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any(),
eq(null)
)
).thenReturn(
AuthenticationRequestMock(
Credentials(
"expectedIdToken",
Expand Down Expand Up @@ -324,7 +336,10 @@ public class PasskeyManagerTest {
any(),
any()
)
verify(authenticationAPIClient).signinWithPasskey(any(), any<PublicKeyCredentials>(), any())
verify(authenticationAPIClient).signinWithPasskey(
any(), any<PublicKeyCredentials>(), any(),
eq(null)
)
verify(callback).onSuccess(credentialsCaptor.capture())
Assert.assertEquals("codeAccess", credentialsCaptor.firstValue.accessToken)
Assert.assertEquals("codeScope", credentialsCaptor.firstValue.scope)
Expand All @@ -342,15 +357,20 @@ public class PasskeyManagerTest {

passkeyManager.signin(context, "testRealm", parameters, callback, serialExecutor)

verify(authenticationAPIClient).passkeyChallenge(any())
verify(authenticationAPIClient).passkeyChallenge(any(), eq(null))
verify(credentialManager, never()).getCredentialAsync(
any(),
any<GetCredentialRequest>(),
any(),
any(),
any()
)
verify(authenticationAPIClient, never()).signinWithPasskey(any(), any<PublicKeyCredentials>(), any())
verify(authenticationAPIClient, never()).signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any(),
eq(null)
)
verify(callback).onFailure(error)
}

Expand Down Expand Up @@ -384,7 +404,12 @@ public class PasskeyManagerTest {
any(),
any()
)
verify(authenticationAPIClient, never()).signinWithPasskey(any(), any<PublicKeyCredentials>(), any())
verify(authenticationAPIClient, never()).signinWithPasskey(
any(),
any<PublicKeyCredentials>(),
any(),
eq(null)
)
verify(callback).onFailure(exceptionCaptor.capture())
Assert.assertEquals(
AuthenticationException::class.java,
Expand Down