|
1 | 1 | package com.auth0.client.auth; |
2 | 2 |
|
3 | 3 | import com.auth0.client.mgmt.ManagementAPI; |
4 | | -import com.auth0.json.auth.PasswordlessEmailResponse; |
5 | | -import com.auth0.json.auth.PasswordlessSmsResponse; |
6 | | -import com.auth0.json.auth.UserInfo; |
| 4 | +import com.auth0.json.auth.*; |
7 | 5 | import com.auth0.net.*; |
8 | 6 | import com.auth0.net.client.Auth0HttpClient; |
9 | 7 | import com.auth0.net.client.DefaultHttpClient; |
|
14 | 12 | import okhttp3.OkHttpClient; |
15 | 13 | import org.jetbrains.annotations.TestOnly; |
16 | 14 |
|
| 15 | +import java.util.Collections; |
| 16 | +import java.util.List; |
17 | 17 | import java.util.Objects; |
18 | 18 |
|
19 | 19 | /** |
@@ -896,6 +896,250 @@ public TokenRequest exchangeMfaOtp(String mfaToken, char[] otp) { |
896 | 896 | return request; |
897 | 897 | } |
898 | 898 |
|
| 899 | + /** |
| 900 | + * Creates a request to exchange the mfa token and an out-of-band (OOB) challenge (either Push notification, SMS, or Voice). |
| 901 | + * Confidential clients (Regular Web Apps) <strong>must</strong> have a client secret configured on this {@code AuthAPI} instance. |
| 902 | + * <pre> |
| 903 | + * {@code |
| 904 | + * try { |
| 905 | + * TokenHolder result = authAPI.exchangeMfaOob("the-mfa-token", new char[]{'a','n','o','t','p'}, new char[]{'b','i','n','d','c','o','d','e'}) |
| 906 | + * .execute() |
| 907 | + * .getBody(); |
| 908 | + * } catch (Auth0Exception e) { |
| 909 | + * //Something happened |
| 910 | + * } |
| 911 | + * } |
| 912 | + * </pre> |
| 913 | + * |
| 914 | + * @param mfaToken the mfa_token received from the mfa_required error that occurred during login. Must not be null. |
| 915 | + * @param oobCode the OOB Code provided by the user. Must not be null. |
| 916 | + * @param bindingCode A 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. May be null. |
| 917 | + * |
| 918 | + * @return a Request to configure and execute. |
| 919 | + * |
| 920 | + * @see <a href="https://auth0.com/docs/api/authentication#verify-with-out-of-band-oob-">Verify with Out-of-band (OOB) API documentation</a> |
| 921 | + */ |
| 922 | + public TokenRequest exchangeMfaOob(String mfaToken, char[] oobCode, char[] bindingCode) { |
| 923 | + Asserts.assertNotNull(mfaToken, "mfa token"); |
| 924 | + Asserts.assertNotNull(oobCode, "OOB code"); |
| 925 | + |
| 926 | + TokenRequest request = new TokenRequest(client, getTokenUrl()); |
| 927 | + request.addParameter(KEY_CLIENT_ID, clientId); |
| 928 | + request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/mfa-oob"); |
| 929 | + request.addParameter(KEY_MFA_TOKEN, mfaToken); |
| 930 | + request.addParameter("oob_code", oobCode); |
| 931 | + |
| 932 | + if (Objects.nonNull(bindingCode) && bindingCode.length > 0) { |
| 933 | + request.addParameter("binding_code", bindingCode); |
| 934 | + } |
| 935 | + |
| 936 | + addSecret(request, false); |
| 937 | + return request; |
| 938 | + } |
| 939 | + |
| 940 | + /** |
| 941 | + * Creates a request to exchange the mfa token using a recovery code. |
| 942 | + * Confidential clients (Regular Web Apps) <strong>must</strong> have a client secret configured on this {@code AuthAPI} instance. |
| 943 | + * <pre> |
| 944 | + * {@code |
| 945 | + * try { |
| 946 | + * TokenHolder result = authAPI.exchangeMfaRecoveryCode("the-mfa-token", new char[]{'c','o','d','e'}) |
| 947 | + * .execute() |
| 948 | + * .getBody(); |
| 949 | + * } catch (Auth0Exception e) { |
| 950 | + * //Something happened |
| 951 | + * } |
| 952 | + * } |
| 953 | + * </pre> |
| 954 | + * |
| 955 | + * @param mfaToken the mfa_token received from the mfa_required error that occurred during login. Must not be null. |
| 956 | + * @param recoveryCode the recovery code provided by the user. Must not be null. |
| 957 | + * @return a Request to configure and execute. |
| 958 | + * |
| 959 | + * @see <a href="https://auth0.com/docs/api/authentication#verify-with-recovery-code">Verify with a recovery code API documentation</a> |
| 960 | + */ |
| 961 | + public TokenRequest exchangeMfaRecoveryCode(String mfaToken, char[] recoveryCode) { |
| 962 | + Asserts.assertNotNull(mfaToken, "mfa token"); |
| 963 | + Asserts.assertNotNull(recoveryCode, "recovery code"); |
| 964 | + |
| 965 | + TokenRequest request = new TokenRequest(client, getTokenUrl()); |
| 966 | + request.addParameter(KEY_CLIENT_ID, clientId); |
| 967 | + request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/mfa-recovery-code"); |
| 968 | + request.addParameter(KEY_MFA_TOKEN, mfaToken); |
| 969 | + request.addParameter("recovery_code", recoveryCode); |
| 970 | + |
| 971 | + addSecret(request, false); |
| 972 | + return request; |
| 973 | + } |
| 974 | + |
| 975 | + /** |
| 976 | + * Request a challenge for multi-factor authentication (MFA) based on the challenge types supported by the application and user. |
| 977 | + * Confidential clients (Regular Web Apps) <strong>must</strong> have a client secret configured on this {@code AuthAPI} instance. |
| 978 | + * <pre> |
| 979 | + * {@code |
| 980 | + * try { |
| 981 | + * MfaChallengeResponse result = authAPI.mfaChallengeRequest("the-mfa-token", "otp", "authenticator-id") |
| 982 | + * .execute() |
| 983 | + * .getBody(); |
| 984 | + * } catch (Auth0Exception e) { |
| 985 | + * //Something happened |
| 986 | + * } |
| 987 | + * } |
| 988 | + * </pre> |
| 989 | + * |
| 990 | + * @param mfaToken The token received from mfa_required error. Must not be null. |
| 991 | + * @param challengeType A whitespace-separated list of the challenges types accepted by your application. |
| 992 | + * @param authenticatorId The ID of the authenticator to challenge. |
| 993 | + * @return a Request to execute. |
| 994 | + * @see <a href="https://auth0.com/docs/api/authentication#challenge-request">Challenge Request API documentation</a> |
| 995 | + */ |
| 996 | + public Request<MfaChallengeResponse> mfaChallengeRequest(String mfaToken, String challengeType, String authenticatorId) { |
| 997 | + Asserts.assertNotNull(mfaToken, "mfa token"); |
| 998 | + |
| 999 | + String url = baseUrl |
| 1000 | + .newBuilder() |
| 1001 | + .addPathSegment("mfa") |
| 1002 | + .addPathSegment("challenge") |
| 1003 | + .build() |
| 1004 | + .toString(); |
| 1005 | + |
| 1006 | + BaseRequest<MfaChallengeResponse> request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference<MfaChallengeResponse>() { |
| 1007 | + }); |
| 1008 | + |
| 1009 | + request.addParameter(KEY_MFA_TOKEN, mfaToken); |
| 1010 | + request.addParameter(KEY_CLIENT_ID, clientId); |
| 1011 | + addSecret(request, false); |
| 1012 | + if (Objects.nonNull(challengeType)) { |
| 1013 | + request.addParameter("challenge_type", challengeType); |
| 1014 | + } |
| 1015 | + if (Objects.nonNull(authenticatorId)) { |
| 1016 | + request.addParameter("authenticator_id", authenticatorId); |
| 1017 | + } |
| 1018 | + return request; |
| 1019 | + } |
| 1020 | + |
| 1021 | + /** |
| 1022 | + * Associates or adds a new OTP authenticator for multi-factor authentication (MFA). |
| 1023 | + * Confidential clients (Regular Web Apps) <strong>must</strong> have a client secret configured on this {@code AuthAPI} instance. |
| 1024 | + * <pre> |
| 1025 | + * {@code |
| 1026 | + * try { |
| 1027 | + * CreatedOTPResponse result = authAPI.addOTPAuthenticator("the-mfa-token") |
| 1028 | + * .execute() |
| 1029 | + * .getBody(); |
| 1030 | + * } catch (Auth0Exception e) { |
| 1031 | + * //Something happened |
| 1032 | + * } |
| 1033 | + * } |
| 1034 | + * </pre> |
| 1035 | + * |
| 1036 | + * @param mfaToken The token received from mfa_required error. Must not be null. |
| 1037 | + * @return a Request to execute. |
| 1038 | + * @see <a href="https://auth0.com/docs/api/authentication#add-an-authenticator">Add an Authenticator API documentation</a> |
| 1039 | + */ |
| 1040 | + public Request<CreatedOtpResponse> addOtpAuthenticator(String mfaToken) { |
| 1041 | + Asserts.assertNotNull(mfaToken, "mfa token"); |
| 1042 | + |
| 1043 | + String url = baseUrl |
| 1044 | + .newBuilder() |
| 1045 | + .addPathSegment("mfa") |
| 1046 | + .addPathSegment("associate") |
| 1047 | + .build() |
| 1048 | + .toString(); |
| 1049 | + |
| 1050 | + BaseRequest<CreatedOtpResponse> request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference<CreatedOtpResponse>() { |
| 1051 | + }); |
| 1052 | + |
| 1053 | + request.addParameter("authenticator_types", Collections.singletonList("otp")); |
| 1054 | + request.addParameter(KEY_CLIENT_ID, clientId); |
| 1055 | + addSecret(request, false); |
| 1056 | + request.addHeader("Authorization", "Bearer " + mfaToken); |
| 1057 | + return request; |
| 1058 | + } |
| 1059 | + |
| 1060 | + /** |
| 1061 | + * Associates or adds a new OOB authenticator for multi-factor authentication (MFA). |
| 1062 | + * Confidential clients (Regular Web Apps) <strong>must</strong> have a client secret configured on this {@code AuthAPI} instance. |
| 1063 | + * <pre> |
| 1064 | + * {@code |
| 1065 | + * try { |
| 1066 | + * CreatedOobResponse result = authAPI.addOobAuthenticator("the-mfa-token", Collections.singletonList("sms"), "phone-number") |
| 1067 | + * .execute() |
| 1068 | + * .getBody(); |
| 1069 | + * } catch (Auth0Exception e) { |
| 1070 | + * //Something happened |
| 1071 | + * } |
| 1072 | + * } |
| 1073 | + * </pre> |
| 1074 | + * |
| 1075 | + * @param mfaToken The token received from mfa_required error. Must not be null. |
| 1076 | + * @param oobChannels The type of OOB channels supported by the client. Must not be null. |
| 1077 | + * @param phoneNumber The phone number for "sms" or "voice" channels. May be null if not using "sms" or "voice". |
| 1078 | + * @return a Request to execute. |
| 1079 | + * @see <a href="https://auth0.com/docs/api/authentication#add-an-authenticator">Add an Authenticator API documentation</a> |
| 1080 | + */ |
| 1081 | + public Request<CreatedOobResponse> addOobAuthenticator(String mfaToken, List<String> oobChannels, String phoneNumber) { |
| 1082 | + Asserts.assertNotNull(mfaToken, "mfa token"); |
| 1083 | + Asserts.assertNotNull(oobChannels, "OOB channels"); |
| 1084 | + |
| 1085 | + String url = baseUrl |
| 1086 | + .newBuilder() |
| 1087 | + .addPathSegment("mfa") |
| 1088 | + .addPathSegment("associate") |
| 1089 | + .build() |
| 1090 | + .toString(); |
| 1091 | + |
| 1092 | + BaseRequest<CreatedOobResponse> request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference<CreatedOobResponse>() { |
| 1093 | + }); |
| 1094 | + |
| 1095 | + request.addParameter("authenticator_types", Collections.singletonList("oob")); |
| 1096 | + request.addParameter("oob_channels", oobChannels); |
| 1097 | + request.addParameter(KEY_CLIENT_ID, clientId); |
| 1098 | + if (phoneNumber != null) { |
| 1099 | + request.addParameter("phone_number", phoneNumber); |
| 1100 | + } |
| 1101 | + addSecret(request, false); |
| 1102 | + request.addHeader("Authorization", "Bearer " + mfaToken); |
| 1103 | + return request; |
| 1104 | + } |
| 1105 | + |
| 1106 | + |
| 1107 | + /** |
| 1108 | + * Returns a list of authenticators associated with your application. |
| 1109 | + * <pre> |
| 1110 | + * {@code |
| 1111 | + * try { |
| 1112 | + * List<MfaAuthenticator> result = authAPI.listAuthenticators("token") |
| 1113 | + * .execute() |
| 1114 | + * .getBody(); |
| 1115 | + * } catch (Auth0Exception e) { |
| 1116 | + * //Something happened |
| 1117 | + * } |
| 1118 | + * } |
| 1119 | + * </pre> |
| 1120 | + * |
| 1121 | + * @param accessToken The Access Token obtained during login. The token must possess a scope of {@code read:authenticators} |
| 1122 | + * and an audience of {@code https://YOUR_DOMAIN/mfa/} |
| 1123 | + * @return a Request to execute. |
| 1124 | + * @see <a href="https://auth0.com/docs/api/authentication#list-authenticators">List authenticators API documentation</a> |
| 1125 | + */ |
| 1126 | + public Request<List<MfaAuthenticator>> listAuthenticators(String accessToken) { |
| 1127 | + Asserts.assertNotNull(accessToken, "access token"); |
| 1128 | + |
| 1129 | + String url = baseUrl |
| 1130 | + .newBuilder() |
| 1131 | + .addPathSegment("mfa") |
| 1132 | + .addPathSegment("authenticators") |
| 1133 | + .build() |
| 1134 | + .toString(); |
| 1135 | + |
| 1136 | + BaseRequest<List<MfaAuthenticator>> request = new BaseRequest<>(client, null, url, HttpMethod.GET, new TypeReference<List<MfaAuthenticator>>() { |
| 1137 | + }); |
| 1138 | + |
| 1139 | + request.addHeader("Authorization", "Bearer " + accessToken); |
| 1140 | + return request; |
| 1141 | + } |
| 1142 | + |
899 | 1143 | private TokenRequest exchangeCode(String code, String redirectUri, boolean secretRequired) { |
900 | 1144 | Asserts.assertNotNull(code, "code"); |
901 | 1145 | Asserts.assertNotNull(redirectUri, "redirect uri"); |
|
0 commit comments