diff --git a/src/main/java/io/fusionauth/client/FusionAuthClient.java b/src/main/java/io/fusionauth/client/FusionAuthClient.java index a77ab4f5..fe41b296 100644 --- a/src/main/java/io/fusionauth/client/FusionAuthClient.java +++ b/src/main/java/io/fusionauth/client/FusionAuthClient.java @@ -237,11 +237,24 @@ import io.fusionauth.domain.api.user.VerifyRegistrationRequest; import io.fusionauth.domain.api.user.VerifyRegistrationResponse; import io.fusionauth.domain.oauth2.AccessToken; +import io.fusionauth.domain.oauth2.AccessTokenIntrospectRequest; +import io.fusionauth.domain.oauth2.ClientCredentialsAccessTokenIntrospectRequest; +import io.fusionauth.domain.oauth2.ClientCredentialsGrantRequest; +import io.fusionauth.domain.oauth2.DeviceApprovalRequest; import io.fusionauth.domain.oauth2.DeviceApprovalResponse; +import io.fusionauth.domain.oauth2.DeviceAuthorizationRequest; +import io.fusionauth.domain.oauth2.DeviceResponse; import io.fusionauth.domain.oauth2.IntrospectResponse; import io.fusionauth.domain.oauth2.JWKSResponse; +import io.fusionauth.domain.oauth2.OAuthCodeAccessTokenRequest; +import io.fusionauth.domain.oauth2.OAuthCodePKCEAccessTokenRequest; import io.fusionauth.domain.oauth2.OAuthError; +import io.fusionauth.domain.oauth2.RefreshTokenAccessTokenRequest; +import io.fusionauth.domain.oauth2.RetrieveUserCodeRequest; +import io.fusionauth.domain.oauth2.RetrieveUserCodeUsingAPIKeyRequest; +import io.fusionauth.domain.oauth2.UserCredentialsAccessTokenRequest; import io.fusionauth.domain.oauth2.UserinfoResponse; +import io.fusionauth.domain.oauth2.ValidateDeviceRequest; import io.fusionauth.domain.provider.IdentityProviderType; /** @@ -403,6 +416,20 @@ public ClientResponse approveDevice(String clien .go(); } + /** + * Approve a device grant. + * + * @param request The request object containing the device approval information and optional tenantId. + * @return The ClientResponse object. + */ + public ClientResponse approveDeviceWithRequest(DeviceApprovalRequest request) { + return start(DeviceApprovalResponse.class, Errors.class) + .uri("/oauth2/device/approve") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Cancels the user action. * @@ -592,6 +619,20 @@ public ClientResponse clientCredentialsGrant(String cli .go(); } + /** + * Make a Client Credentials grant request to obtain an access token. + * + * @param request The client credentials grant request containing client authentication, scope and optional tenantId. + * @return The ClientResponse object. + */ + public ClientResponse clientCredentialsGrantWithRequest(ClientCredentialsGrantRequest request) { + return startAnonymous(AccessToken.class, OAuthError.class) + .uri("/oauth2/token") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Adds a comment to the user's account. * @@ -1787,6 +1828,40 @@ public ClientResponse deleteWebhook(UUID webhookId) { .go(); } + /** + * Start the Device Authorization flow using form-encoded parameters + * + * @param client_id The unique client identifier. The client Id is the Id of the FusionAuth Application in which you are attempting to authenticate. + * @param client_secret (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. + * @param scope (Optional) A space-delimited string of the requested scopes. Defaults to all scopes configured in the Application's OAuth configuration. + * @return The ClientResponse object. + */ + public ClientResponse deviceAuthorize(String client_id, String client_secret, String scope) { + Map> parameters = new HashMap<>(); + parameters.put("client_id", Arrays.asList(client_id)); + parameters.put("client_secret", Arrays.asList(client_secret)); + parameters.put("scope", Arrays.asList(scope)); + return startAnonymous(DeviceResponse.class, OAuthError.class) + .uri("/oauth2/device_authorize") + .bodyHandler(new FormDataBodyHandler(parameters)) + .post() + .go(); + } + + /** + * Start the Device Authorization flow using a request body + * + * @param request The device authorization request containing client authentication, scope, and optional device metadata. + * @return The ClientResponse object. + */ + public ClientResponse deviceAuthorizeWithRequest(DeviceAuthorizationRequest request) { + return startAnonymous(DeviceResponse.class, OAuthError.class) + .uri("/oauth2/device_authorize") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Disable two-factor authentication for a user. * @@ -1889,6 +1964,36 @@ public ClientResponse exchangeOAuthCodeForAccessTokenUs .go(); } + /** + * Exchanges an OAuth authorization code and code_verifier for an access token. + * Makes a request to the Token endpoint to exchange the authorization code returned from the Authorize endpoint and a code_verifier for an access token. + * + * @param request The PKCE OAuth code access token exchange request. + * @return The ClientResponse object. + */ + public ClientResponse exchangeOAuthCodeForAccessTokenUsingPKCEWithRequest(OAuthCodePKCEAccessTokenRequest request) { + return startAnonymous(AccessToken.class, OAuthError.class) + .uri("/oauth2/token") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + + /** + * Exchanges an OAuth authorization code for an access token. + * Makes a request to the Token endpoint to exchange the authorization code returned from the Authorize endpoint for an access token. + * + * @param request The OAuth code access token exchange request. + * @return The ClientResponse object. + */ + public ClientResponse exchangeOAuthCodeForAccessTokenWithRequest(OAuthCodeAccessTokenRequest request) { + return startAnonymous(AccessToken.class, OAuthError.class) + .uri("/oauth2/token") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Exchange a Refresh Token for an Access Token. * If you will be using the Refresh Token Grant, you will make a request to the Token endpoint to exchange the user’s refresh token for an access token. @@ -1916,6 +2021,21 @@ public ClientResponse exchangeRefreshTokenForAccessToke .go(); } + /** + * Exchange a Refresh Token for an Access Token. + * If you will be using the Refresh Token Grant, you will make a request to the Token endpoint to exchange the user’s refresh token for an access token. + * + * @param request The refresh token access token exchange request. + * @return The ClientResponse object. + */ + public ClientResponse exchangeRefreshTokenForAccessTokenWithRequest(RefreshTokenAccessTokenRequest request) { + return startAnonymous(AccessToken.class, OAuthError.class) + .uri("/oauth2/token") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Exchange a refresh token for a new JWT. * @@ -1959,6 +2079,21 @@ public ClientResponse exchangeUserCredentialsForAccessT .go(); } + /** + * Exchange User Credentials for a Token. + * If you will be using the Resource Owner Password Credential Grant, you will make a request to the Token endpoint to exchange the user’s email and password for an access token. + * + * @param request The user credentials access token exchange request. + * @return The ClientResponse object. + */ + public ClientResponse exchangeUserCredentialsForAccessTokenWithRequest(UserCredentialsAccessTokenRequest request) { + return startAnonymous(AccessToken.class, OAuthError.class) + .uri("/oauth2/token") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. * @@ -2173,6 +2308,20 @@ public ClientResponse introspectAccessToken(Stri .go(); } + /** + * Inspect an access token issued as the result of the User based grant such as the Authorization Code Grant, Implicit Grant, the User Credentials Grant or the Refresh Grant. + * + * @param request The access token introspection request. + * @return The ClientResponse object. + */ + public ClientResponse introspectAccessTokenWithRequest(AccessTokenIntrospectRequest request) { + return startAnonymous(IntrospectResponse.class, OAuthError.class) + .uri("/oauth2/introspect") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Inspect an access token issued as the result of the Client Credentials Grant. * @@ -2189,6 +2338,20 @@ public ClientResponse introspectClientCredential .go(); } + /** + * Inspect an access token issued as the result of the Client Credentials Grant. + * + * @param request The client credentials access token. + * @return The ClientResponse object. + */ + public ClientResponse introspectClientCredentialsAccessTokenWithRequest(ClientCredentialsAccessTokenIntrospectRequest request) { + return startAnonymous(IntrospectResponse.class, OAuthError.class) + .uri("/oauth2/introspect") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Issue a new access token (JWT) for the requested Application after ensuring the provided JWT is valid. A valid * access token is properly signed and not expired. @@ -4323,6 +4486,40 @@ public ClientResponse retrieveUserCodeUsingAPIKey(String user_code) .go(); } + /** + * Retrieve a user_code that is part of an in-progress Device Authorization Grant. + *

+ * This API is useful if you want to build your own login workflow to complete a device grant. + *

+ * This request will require an API key. + * + * @param request The user code retrieval request including optional tenantId. + * @return The ClientResponse object. + */ + public ClientResponse retrieveUserCodeUsingAPIKeyWithRequest(RetrieveUserCodeUsingAPIKeyRequest request) { + return startAnonymous(Void.TYPE, Void.TYPE) + .uri("/oauth2/device/user-code") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + + /** + * Retrieve a user_code that is part of an in-progress Device Authorization Grant. + *

+ * This API is useful if you want to build your own login workflow to complete a device grant. + * + * @param request The user code retrieval request. + * @return The ClientResponse object. + */ + public ClientResponse retrieveUserCodeWithRequest(RetrieveUserCodeRequest request) { + return startAnonymous(Void.TYPE, Void.TYPE) + .uri("/oauth2/device/user-code") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Retrieves all the comments for the user with the given Id. * @@ -5862,6 +6059,21 @@ public ClientResponse validateDevice(String user_code, String client .go(); } + /** + * Validates the end-user provided user_code from the user-interaction of the Device Authorization Grant. + * If you build your own activation form you should validate the user provided code prior to beginning the Authorization grant. + * + * @param request The device validation request. + * @return The ClientResponse object. + */ + public ClientResponse validateDeviceWithRequest(ValidateDeviceRequest request) { + return startAnonymous(Void.TYPE, Void.TYPE) + .uri("/oauth2/device/validate") + .bodyHandler(new JSONBodyHandler(request, objectMapper())) + .post() + .go(); + } + /** * Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly * signed and not expired.