diff --git a/src/FusionAuthClient.ts b/src/FusionAuthClient.ts index 8b68124..d8c711c 100644 --- a/src/FusionAuthClient.ts +++ b/src/FusionAuthClient.ts @@ -122,6 +122,37 @@ export class FusionAuthClient { .go(); } + /** + * Approve a device grant. + * + * @param {DeviceApprovalRequest} request The request object containing the device approval information and optional tenantId. + * @returns {Promise>} + */ + approveDeviceWithRequest(request: DeviceApprovalRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + if (request.token !== null && request.token !== undefined) { + body.append('token', request.token); + } + if (request.user_code !== null && request.user_code !== undefined) { + body.append('user_code', request.user_code); + } + return this.start() + .withUri('/oauth2/device/approve') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Cancels the user action. * @@ -394,6 +425,37 @@ export class FusionAuthClient { .go(); } + /** + * Make a Client Credentials grant request to obtain an access token. + * + * @param {ClientCredentialsGrantRequest} request The client credentials grant request containing client authentication, scope and optional tenantId. + * @returns {Promise>} + */ + clientCredentialsGrantWithRequest(request: ClientCredentialsGrantRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.grant_type !== null && request.grant_type !== undefined) { + body.append('grant_type', request.grant_type); + } + if (request.scope !== null && request.scope !== undefined) { + body.append('scope', request.scope); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId); + } + return this.startAnonymous() + .withUri('/oauth2/token') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Adds a comment to the user's account. * @@ -1589,6 +1651,55 @@ export class FusionAuthClient { .go(); } + /** + * Start the Device Authorization flow using form-encoded parameters + * + * @param {string} client_id The unique client identifier. The client Id is the Id of the FusionAuth Application in which you are attempting to authenticate. + * @param {string} client_secret (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. + * @param {string} scope (Optional) A space-delimited string of the requested scopes. Defaults to all scopes configured in the Application's OAuth configuration. + * @returns {Promise>} + */ + deviceAuthorize(client_id: string, client_secret: string, scope: string): Promise> { + let body = new URLSearchParams(); + + body.append('client_id', client_id); + body.append('client_secret', client_secret); + body.append('scope', scope); + return this.startAnonymous() + .withUri('/oauth2/device_authorize') + .withFormData(body) + .withMethod("POST") + .go(); + } + + /** + * Start the Device Authorization flow using a request body + * + * @param {DeviceAuthorizationRequest} request The device authorization request containing client authentication, scope, and optional device metadata. + * @returns {Promise>} + */ + deviceAuthorizeWithRequest(request: DeviceAuthorizationRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.scope !== null && request.scope !== undefined) { + body.append('scope', request.scope); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + return this.startAnonymous() + .withUri('/oauth2/device_authorize') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Disable two-factor authentication for a user. * @@ -1693,6 +1804,79 @@ export class FusionAuthClient { .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 {OAuthCodePKCEAccessTokenRequest} request The PKCE OAuth code access token exchange request. + * @returns {Promise>} + */ + exchangeOAuthCodeForAccessTokenUsingPKCEWithRequest(request: OAuthCodePKCEAccessTokenRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.code !== null && request.code !== undefined) { + body.append('code', request.code); + } + if (request.code_verifier !== null && request.code_verifier !== undefined) { + body.append('code_verifier', request.code_verifier); + } + if (request.grant_type !== null && request.grant_type !== undefined) { + body.append('grant_type', request.grant_type); + } + if (request.redirect_uri !== null && request.redirect_uri !== undefined) { + body.append('redirect_uri', request.redirect_uri); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + return this.startAnonymous() + .withUri('/oauth2/token') + .withFormData(body) + .withMethod("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 {OAuthCodeAccessTokenRequest} request The OAuth code access token exchange request. + * @returns {Promise>} + */ + exchangeOAuthCodeForAccessTokenWithRequest(request: OAuthCodeAccessTokenRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.code !== null && request.code !== undefined) { + body.append('code', request.code); + } + if (request.grant_type !== null && request.grant_type !== undefined) { + body.append('grant_type', request.grant_type); + } + if (request.redirect_uri !== null && request.redirect_uri !== undefined) { + body.append('redirect_uri', request.redirect_uri); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId); + } + return this.startAnonymous() + .withUri('/oauth2/token') + .withFormData(body) + .withMethod("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. @@ -1721,6 +1905,44 @@ export class FusionAuthClient { .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 {RefreshTokenAccessTokenRequest} request The refresh token access token exchange request. + * @returns {Promise>} + */ + exchangeRefreshTokenForAccessTokenWithRequest(request: RefreshTokenAccessTokenRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.grant_type !== null && request.grant_type !== undefined) { + body.append('grant_type', request.grant_type); + } + if (request.refresh_token !== null && request.refresh_token !== undefined) { + body.append('refresh_token', request.refresh_token); + } + if (request.scope !== null && request.scope !== undefined) { + body.append('scope', request.scope); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + if (request.user_code !== null && request.user_code !== undefined) { + body.append('user_code', request.user_code); + } + return this.startAnonymous() + .withUri('/oauth2/token') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Exchange a refresh token for a new JWT. * @@ -1765,6 +1987,47 @@ export class FusionAuthClient { .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 {UserCredentialsAccessTokenRequest} request The user credentials access token exchange request. + * @returns {Promise>} + */ + exchangeUserCredentialsForAccessTokenWithRequest(request: UserCredentialsAccessTokenRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.grant_type !== null && request.grant_type !== undefined) { + body.append('grant_type', request.grant_type); + } + if (request.password !== null && request.password !== undefined) { + body.append('password', request.password); + } + if (request.scope !== null && request.scope !== undefined) { + body.append('scope', request.scope); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId); + } + if (request.user_code !== null && request.user_code !== undefined) { + body.append('user_code', request.user_code); + } + if (request.username !== null && request.username !== undefined) { + body.append('username', request.username); + } + return this.startAnonymous() + .withUri('/oauth2/token') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. * @@ -1981,6 +2244,31 @@ export class FusionAuthClient { .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 {AccessTokenIntrospectRequest} request The access token introspection request. + * @returns {Promise>} + */ + introspectAccessTokenWithRequest(request: AccessTokenIntrospectRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId); + } + if (request.token !== null && request.token !== undefined) { + body.append('token', request.token); + } + return this.startAnonymous() + .withUri('/oauth2/introspect') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Inspect an access token issued as the result of the Client Credentials Grant. * @@ -1998,6 +2286,28 @@ export class FusionAuthClient { .go(); } + /** + * Inspect an access token issued as the result of the Client Credentials Grant. + * + * @param {ClientCredentialsAccessTokenIntrospectRequest} request The client credentials access token. + * @returns {Promise>} + */ + introspectClientCredentialsAccessTokenWithRequest(request: ClientCredentialsAccessTokenIntrospectRequest): Promise> { + let body = new URLSearchParams(); + + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId); + } + if (request.token !== null && request.token !== undefined) { + body.append('token', request.token); + } + return this.startAnonymous() + .withUri('/oauth2/introspect') + .withFormData(body) + .withMethod("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. @@ -4153,6 +4463,62 @@ export class FusionAuthClient { .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 {RetrieveUserCodeUsingAPIKeyRequest} request The user code retrieval request including optional tenantId. + * @returns {Promise>} + */ + retrieveUserCodeUsingAPIKeyWithRequest(request: RetrieveUserCodeUsingAPIKeyRequest): Promise> { + let body = new URLSearchParams(); + + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + if (request.user_code !== null && request.user_code !== undefined) { + body.append('user_code', request.user_code); + } + return this.startAnonymous() + .withUri('/oauth2/device/user-code') + .withFormData(body) + .withMethod("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 {RetrieveUserCodeRequest} request The user code retrieval request. + * @returns {Promise>} + */ + retrieveUserCodeWithRequest(request: RetrieveUserCodeRequest): Promise> { + let body = new URLSearchParams(); + + if (request.client_id !== null && request.client_id !== undefined) { + body.append('client_id', request.client_id); + } + if (request.client_secret !== null && request.client_secret !== undefined) { + body.append('client_secret', request.client_secret); + } + if (request.tenantId !== null && request.tenantId !== undefined) { + body.append('tenantId', request.tenantId.toString()); + } + if (request.user_code !== null && request.user_code !== undefined) { + body.append('user_code', request.user_code); + } + return this.startAnonymous() + .withUri('/oauth2/device/user-code') + .withFormData(body) + .withMethod("POST") + .go(); + } + /** * Retrieves all the comments for the user with the given Id. * @@ -5693,6 +6059,23 @@ export class FusionAuthClient { .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 {ValidateDeviceRequest} request The device validation request. + * @returns {Promise>} + */ + validateDeviceWithRequest(request: ValidateDeviceRequest): Promise> { + return this.startAnonymous() + .withUri('/oauth2/device/validate') + .withParameter('client_id', request.client_id) + .withParameter('tenantId', request.tenantId != null ? request.tenantId.toString() : null) + .withParameter('user_code', request.user_code) + .withMethod("GET") + .go(); + } + /** * Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly * signed and not expired. @@ -5934,6 +6317,17 @@ export interface AccessToken { userId?: UUID; } +/** + * The request object for introspecting an access token. + * + * @author Lyle Schemmerling + */ +export interface AccessTokenIntrospectRequest { + client_id?: string; + tenantId?: string; + token?: string; +} + /** * The user action request object. * @@ -6812,6 +7206,29 @@ export enum ClientAuthenticationPolicy { NotRequiredWhenUsingPKCE = "NotRequiredWhenUsingPKCE" } +/** + * Contains the parameters used to introspect an access token that was obtained via the client credentials grant. + * + * @author Lyle Schemmerling + */ +export interface ClientCredentialsAccessTokenIntrospectRequest { + tenantId?: string; + token?: string; +} + +/** + * The request object to make a Client Credentials grant request to obtain an access token. + * + * @author Lyle Schemmerling + */ +export interface ClientCredentialsGrantRequest { + client_id?: string; + client_secret?: string; + grant_type?: string; + scope?: string; + tenantId?: string; +} + /** * @author Trevor Smith */ @@ -7029,6 +7446,19 @@ export interface DailyActiveUserReportResponse { total?: number; } +/** + * The request object to approve a device grant. + * + * @author Lyle Schemmerling + */ +export interface DeviceApprovalRequest { + client_id?: string; + client_secret?: string; + tenantId?: UUID; + token?: string; + user_code?: string; +} + /** * @author Daniel DeGroff */ @@ -7040,6 +7470,16 @@ export interface DeviceApprovalResponse { userId?: UUID; } +/** + * @author Lyle Schemmerling + */ +export interface DeviceAuthorizationRequest { + client_id?: string; + client_secret?: string; + scope?: string; + tenantId?: UUID; +} + /** * @author Daniel DeGroff */ @@ -9663,6 +10103,36 @@ export enum OAuthApplicationRelationship { ThirdParty = "ThirdParty" } +/** + * The request object for exchanging an OAuth authorization code for an access token. + * + * @author Lyle Schemmerling + */ +export interface OAuthCodeAccessTokenRequest { + client_id?: string; + client_secret?: string; + code?: string; + grant_type?: string; + redirect_uri?: string; + tenantId?: string; +} + +/** + * The request object to make a request to the Token endpoint to exchange the authorization code returned from the Authorize endpoint and a + * code_verifier for an access token. + * + * @author Lyle Schemmerling + */ +export interface OAuthCodePKCEAccessTokenRequest { + client_id?: string; + client_secret?: string; + code?: string; + code_verifier?: string; + grant_type?: string; + redirect_uri?: string; + tenantId?: UUID; +} + /** * @author Daniel DeGroff */ @@ -10322,6 +10792,21 @@ export interface MetaData { scopes?: Array; } +/** + * The request object to exchange a Refresh Token for an Access Token. + * + * @author Lyle Schemmerling + */ +export interface RefreshTokenAccessTokenRequest { + client_id?: string; + client_secret?: string; + grant_type?: string; + refresh_token?: string; + scope?: string; + tenantId?: UUID; + user_code?: string; +} + /** * @author Daniel DeGroff */ @@ -10517,6 +11002,28 @@ export enum ResidentKeyRequirement { required = "required" } +/** + * The request object for retrieving a user code that is part of an in-progress Device Authorization Grant. + * + * @author Lyle Schemmerling + */ +export interface RetrieveUserCodeRequest { + client_id?: string; + client_secret?: string; + tenantId?: UUID; + user_code?: string; +} + +/** + * The request object for retrieving a user code that is part of an in-progress Device Authorization Grant using an API key + * + * @author Lyle Schemmerling + */ +export interface RetrieveUserCodeUsingAPIKeyRequest { + tenantId?: UUID; + user_code?: string; +} + /** * @author Brian Pontarelli */ @@ -11999,6 +12506,22 @@ export interface UserCreateCompleteEvent extends BaseUserEvent { export interface UserCreateEvent extends BaseUserEvent { } +/** + * The request object for exchanging user credentials (username and password) for an access token. + * + * @author Lyle Schemmerling + */ +export interface UserCredentialsAccessTokenRequest { + client_id?: string; + client_secret?: string; + grant_type?: string; + password?: string; + scope?: string; + tenantId?: string; + user_code?: string; + username?: string; +} + /** * Models the User Deactivate Event. * @@ -12486,6 +13009,17 @@ export enum UserVerificationRequirement { export interface UserinfoResponse extends Record { } +/** + * The request object for validating an end-user provided user_code from the user-interaction of the Device Authorization Grant + * + * @author Lyle Schemmerling + */ +export interface ValidateDeviceRequest { + client_id?: string; + tenantId?: UUID; + user_code?: string; +} + /** * @author Daniel DeGroff */