From 764f582b2f906c67ff597e90d6b817f9b433a752 Mon Sep 17 00:00:00 2001 From: Lyle Schemmerling Date: Wed, 17 Sep 2025 16:47:58 -0600 Subject: [PATCH 1/3] new optional tenant id param added (breaking) --- .../src/io/fusionauth/FusionAuthClient.cs | 36 ++++++---- .../src/io/fusionauth/FusionAuthSyncClient.cs | 48 ++++++------- .../src/io/fusionauth/IFusionAuthClient.cs | 72 ++++++++++++------- 3 files changed, 96 insertions(+), 60 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs index cebab182..6eb7a22f 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs @@ -119,12 +119,13 @@ public Task> AddUserToFamilyAsync(Guid? familyId, } /// - public Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code) { + public Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code, Guid? tenantId) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, { "token", token }, { "user_code", user_code }, + { "tenantId", tenantId }, }; return buildClient() .withUri("/oauth2/device/approve") @@ -211,12 +212,13 @@ public Task> CheckChangePasswordUsingLoginIdAsync(strin } /// - public Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope) { + public Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope, Guid? tenantId) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, { "grant_type", "client_credentials" }, { "scope", scope }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -998,13 +1000,14 @@ public Task> EnableTwoFactorAsync(Guid? userId } /// - public Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri) { + public Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId) { var body = new Dictionary { { "code", code }, { "client_id", client_id }, { "client_secret", client_secret }, { "grant_type", "authorization_code" }, { "redirect_uri", redirect_uri }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1014,7 +1017,7 @@ public Task> ExchangeOAuthCodeForAccessTokenAsync(st } /// - public Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier) { + public Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId) { var body = new Dictionary { { "code", code }, { "client_id", client_id }, @@ -1022,6 +1025,7 @@ public Task> ExchangeOAuthCodeForAccessTokenUsingPKC { "grant_type", "authorization_code" }, { "redirect_uri", redirect_uri }, { "code_verifier", code_verifier }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1031,7 +1035,7 @@ public Task> ExchangeOAuthCodeForAccessTokenUsingPKC } /// - public Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code) { + public Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { var body = new Dictionary { { "refresh_token", refresh_token }, { "client_id", client_id }, @@ -1039,6 +1043,7 @@ public Task> ExchangeRefreshTokenForAccessTokenAsync { "grant_type", "refresh_token" }, { "scope", scope }, { "user_code", user_code }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1057,7 +1062,7 @@ public Task> ExchangeRefreshTokenForJWTAsync( } /// - public Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code) { + public Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { var body = new Dictionary { { "username", username }, { "password", password }, @@ -1066,6 +1071,7 @@ public Task> ExchangeUserCredentialsForAccessTokenAs { "grant_type", "password" }, { "scope", scope }, { "user_code", user_code }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1187,10 +1193,11 @@ public Task> ImportWebAuthnCredentialAsync(WebAuthnCred } /// - public Task> IntrospectAccessTokenAsync(string client_id, string token) { + public Task> IntrospectAccessTokenAsync(string client_id, string token, Guid? tenantId) { var body = new Dictionary { { "client_id", client_id }, { "token", token }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/introspect") @@ -1200,9 +1207,10 @@ public Task> IntrospectAccessTokenAsync(strin } /// - public Task> IntrospectClientCredentialsAccessTokenAsync(string token) { + public Task> IntrospectClientCredentialsAccessTokenAsync(string token, Guid? tenantId) { var body = new Dictionary { { "token", token }, + { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/introspect") @@ -2507,7 +2515,7 @@ public Task> RetrieveUserByVerificationIdAsync(stri } /// - public Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code) { + public Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code, Guid? tenantId) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, @@ -2515,18 +2523,20 @@ public Task> RetrieveUserCodeAsync(string client_id, st }; return buildAnonymousClient() .withUri("/oauth2/device/user-code") + .withParameter("tenantId", tenantId) .withFormData(new FormUrlEncodedContent(body)) .withMethod("Get") .goAsync(); } /// - public Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code) { + public Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code, Guid? tenantId) { var body = new Dictionary { { "user_code", user_code }, }; return buildAnonymousClient() .withUri("/oauth2/device/user-code") + .withParameter("tenantId", tenantId) .withFormData(new FormUrlEncodedContent(body)) .withMethod("Get") .goAsync(); @@ -2560,10 +2570,11 @@ public Task> RetrieveUserConsentsAsync(Guid? } /// - public Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT) { + public Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT, Guid? tenantId) { return buildAnonymousClient() .withUri("/oauth2/userinfo") .withAuthorization("Bearer " + encodedJWT) + .withParameter("tenantId", tenantId) .withMethod("Get") .goAsync(); } @@ -3473,11 +3484,12 @@ public Task> UpsertEntityGrantAsync(Guid? entityId, Ent } /// - public Task> ValidateDeviceAsync(string user_code, string client_id) { + public Task> ValidateDeviceAsync(string user_code, string client_id, Guid? tenantId) { return buildAnonymousClient() .withUri("/oauth2/device/validate") .withParameter("user_code", user_code) .withParameter("client_id", client_id) + .withParameter("tenantId", tenantId) .withMethod("Get") .goAsync(); } diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs index ca33255a..130684fa 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs @@ -72,8 +72,8 @@ public ClientResponse AddUserToFamily(Guid? familyId, FamilyRequ } /// - public ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code) { - return client.ApproveDeviceAsync(client_id, client_secret, token, user_code).GetAwaiter().GetResult(); + public ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code, Guid? tenantId) { + return client.ApproveDeviceAsync(client_id, client_secret, token, user_code, tenantId).GetAwaiter().GetResult(); } /// @@ -118,8 +118,8 @@ public ClientResponse CheckChangePasswordUsingLoginId(string loginId) } /// - public ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope) { - return client.ClientCredentialsGrantAsync(client_id, client_secret, scope).GetAwaiter().GetResult(); + public ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope, Guid? tenantId) { + return client.ClientCredentialsGrantAsync(client_id, client_secret, scope, tenantId).GetAwaiter().GetResult(); } /// @@ -520,18 +520,18 @@ public ClientResponse EnableTwoFactor(Guid? userId, TwoFactor } /// - public ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri) { - return client.ExchangeOAuthCodeForAccessTokenAsync(code, client_id, client_secret, redirect_uri).GetAwaiter().GetResult(); + public ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId) { + return client.ExchangeOAuthCodeForAccessTokenAsync(code, client_id, client_secret, redirect_uri, tenantId).GetAwaiter().GetResult(); } /// - public ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier) { - return client.ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(code, client_id, client_secret, redirect_uri, code_verifier).GetAwaiter().GetResult(); + public ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId) { + return client.ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(code, client_id, client_secret, redirect_uri, code_verifier, tenantId).GetAwaiter().GetResult(); } /// - public ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code) { - return client.ExchangeRefreshTokenForAccessTokenAsync(refresh_token, client_id, client_secret, scope, user_code).GetAwaiter().GetResult(); + public ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { + return client.ExchangeRefreshTokenForAccessTokenAsync(refresh_token, client_id, client_secret, scope, user_code, tenantId).GetAwaiter().GetResult(); } /// @@ -540,8 +540,8 @@ public ClientResponse ExchangeRefreshTokenForJWT(RefreshRequ } /// - public ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code) { - return client.ExchangeUserCredentialsForAccessTokenAsync(username, password, client_id, client_secret, scope, user_code).GetAwaiter().GetResult(); + public ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { + return client.ExchangeUserCredentialsForAccessTokenAsync(username, password, client_id, client_secret, scope, user_code, tenantId).GetAwaiter().GetResult(); } /// @@ -605,13 +605,13 @@ public ClientResponse ImportWebAuthnCredential(WebAuthnCredentialImpor } /// - public ClientResponse IntrospectAccessToken(string client_id, string token) { - return client.IntrospectAccessTokenAsync(client_id, token).GetAwaiter().GetResult(); + public ClientResponse IntrospectAccessToken(string client_id, string token, Guid? tenantId) { + return client.IntrospectAccessTokenAsync(client_id, token, tenantId).GetAwaiter().GetResult(); } /// - public ClientResponse IntrospectClientCredentialsAccessToken(string token) { - return client.IntrospectClientCredentialsAccessTokenAsync(token).GetAwaiter().GetResult(); + public ClientResponse IntrospectClientCredentialsAccessToken(string token, Guid? tenantId) { + return client.IntrospectClientCredentialsAccessTokenAsync(token, tenantId).GetAwaiter().GetResult(); } /// @@ -1315,13 +1315,13 @@ public ClientResponse RetrieveUserByVerificationId(string verifica } /// - public ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code) { - return client.RetrieveUserCodeAsync(client_id, client_secret, user_code).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code, Guid? tenantId) { + return client.RetrieveUserCodeAsync(client_id, client_secret, user_code, tenantId).GetAwaiter().GetResult(); } /// - public ClientResponse RetrieveUserCodeUsingAPIKey(string user_code) { - return client.RetrieveUserCodeUsingAPIKeyAsync(user_code).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserCodeUsingAPIKey(string user_code, Guid? tenantId) { + return client.RetrieveUserCodeUsingAPIKeyAsync(user_code, tenantId).GetAwaiter().GetResult(); } /// @@ -1340,8 +1340,8 @@ public ClientResponse RetrieveUserConsents(Guid? userId) { } /// - public ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT) { - return client.RetrieveUserInfoFromAccessTokenAsync(encodedJWT).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT, Guid? tenantId) { + return client.RetrieveUserInfoFromAccessTokenAsync(encodedJWT, tenantId).GetAwaiter().GetResult(); } /// @@ -1819,8 +1819,8 @@ public ClientResponse UpsertEntityGrant(Guid? entityId, EntityGrantReq } /// - public ClientResponse ValidateDevice(string user_code, string client_id) { - return client.ValidateDeviceAsync(user_code, client_id).GetAwaiter().GetResult(); + public ClientResponse ValidateDevice(string user_code, string client_id, Guid? tenantId) { + return client.ValidateDeviceAsync(user_code, client_id, tenantId).GetAwaiter().GetResult(); } /// diff --git a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs index ebd86e02..26ce754c 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs @@ -84,13 +84,14 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The access token used to identify the user. /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code); + Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code, Guid? tenantId); /// /// Cancels the user action. @@ -234,13 +235,14 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret used to authenticate this request. /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) This parameter is used to indicate which target entity you are requesting access. To request access to an entity, use the format target-entity:<target-entity-id>:<roles>. Roles are an optional comma separated list. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope); + Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope, Guid? tenantId); /// /// Adds a comment to the user's account. @@ -1357,13 +1359,14 @@ public interface IFusionAuthAsyncClient { /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The URI to redirect to upon a successful request. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri); + Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId); /// /// Exchanges an OAuth authorization code and code_verifier for an access token. @@ -1376,13 +1379,14 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// The URI to redirect to upon a successful request. /// The random string generated previously. Will be compared with the code_challenge sent previously, which allows the OAuth provider to authenticate your app. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier); + Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId); /// /// Exchange a Refresh Token for an Access Token. @@ -1395,13 +1399,14 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. + /// (Optional) The Id of the tenant to use for this request. Required if the request is for a universal application. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code); + Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); /// /// Exchange a refresh token for a new JWT. @@ -1428,13 +1433,14 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code); + Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); /// /// Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. @@ -1622,26 +1628,28 @@ public interface IFusionAuthAsyncClient { /// /// The unique client identifier. The client Id is the Id of the FusionAuth Application for which this token was generated. /// The access token returned by this OAuth provider as the result of a successful client credentials grant. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> IntrospectAccessTokenAsync(string client_id, string token); + Task> IntrospectAccessTokenAsync(string client_id, string token, Guid? tenantId); /// /// Inspect an access token issued as the result of the Client Credentials Grant. /// This is an asynchronous method. /// /// The access token returned by this OAuth provider as the result of a successful client credentials grant. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> IntrospectClientCredentialsAccessTokenAsync(string token); + Task> IntrospectClientCredentialsAccessTokenAsync(string token, Guid? tenantId); /// /// Issue a new access token (JWT) for the requested Application after ensuring the provided JWT is valid. A valid @@ -3555,13 +3563,14 @@ public interface IFusionAuthAsyncClient { /// The client Id. /// The client Id. /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code); + Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code, Guid? tenantId); /// /// Retrieve a user_code that is part of an in-progress Device Authorization Grant. @@ -3572,13 +3581,14 @@ public interface IFusionAuthAsyncClient { /// This is an asynchronous method. /// /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code); + Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code, Guid? tenantId); /// /// Retrieves all the comments for the user with the given Id. @@ -3624,13 +3634,14 @@ public interface IFusionAuthAsyncClient { /// This is an asynchronous method. /// /// The encoded JWT (access token). + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT); + Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT, Guid? tenantId); /// /// Retrieve a single Identity Provider user (link). @@ -4953,13 +4964,14 @@ public interface IFusionAuthAsyncClient { /// /// The end-user verification code. /// The client Id. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ValidateDeviceAsync(string user_code, string client_id); + Task> ValidateDeviceAsync(string user_code, string client_id, Guid? tenantId); /// /// Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly @@ -5139,13 +5151,14 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The access token used to identify the user. /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code); + ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code, Guid? tenantId); /// /// Cancels the user action. @@ -5280,13 +5293,14 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret used to authenticate this request. /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) This parameter is used to indicate which target entity you are requesting access. To request access to an entity, use the format target-entity:<target-entity-id>:<roles>. Roles are an optional comma separated list. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope); + ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope, Guid? tenantId); /// /// Adds a comment to the user's account. @@ -6323,13 +6337,14 @@ public interface IFusionAuthSyncClient { /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The URI to redirect to upon a successful request. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri); + ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId); /// /// Exchanges an OAuth authorization code and code_verifier for an access token. @@ -6341,13 +6356,14 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// The URI to redirect to upon a successful request. /// The random string generated previously. Will be compared with the code_challenge sent previously, which allows the OAuth provider to authenticate your app. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier); + ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId); /// /// Exchange a Refresh Token for an Access Token. @@ -6359,13 +6375,14 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. + /// (Optional) The Id of the tenant to use for this request. Required if the request is for a universal application. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code); + ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); /// /// Exchange a refresh token for a new JWT. @@ -6390,13 +6407,14 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code); + ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); /// /// Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. @@ -6571,25 +6589,27 @@ public interface IFusionAuthSyncClient { /// /// The unique client identifier. The client Id is the Id of the FusionAuth Application for which this token was generated. /// The access token returned by this OAuth provider as the result of a successful client credentials grant. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse IntrospectAccessToken(string client_id, string token); + ClientResponse IntrospectAccessToken(string client_id, string token, Guid? tenantId); /// /// Inspect an access token issued as the result of the Client Credentials Grant. /// /// The access token returned by this OAuth provider as the result of a successful client credentials grant. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse IntrospectClientCredentialsAccessToken(string token); + ClientResponse IntrospectClientCredentialsAccessToken(string token, Guid? tenantId); /// /// Issue a new access token (JWT) for the requested Application after ensuring the provided JWT is valid. A valid @@ -8362,13 +8382,14 @@ public interface IFusionAuthSyncClient { /// The client Id. /// The client Id. /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code); + ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code, Guid? tenantId); /// /// Retrieve a user_code that is part of an in-progress Device Authorization Grant. @@ -8378,13 +8399,14 @@ public interface IFusionAuthSyncClient { /// This request will require an API key. /// /// The end-user verification code. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserCodeUsingAPIKey(string user_code); + ClientResponse RetrieveUserCodeUsingAPIKey(string user_code, Guid? tenantId); /// /// Retrieves all the comments for the user with the given Id. @@ -8426,13 +8448,14 @@ public interface IFusionAuthSyncClient { /// Call the UserInfo endpoint to retrieve User Claims from the access token issued by FusionAuth. /// /// The encoded JWT (access token). + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT); + ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT, Guid? tenantId); /// /// Retrieve a single Identity Provider user (link). @@ -9660,13 +9683,14 @@ public interface IFusionAuthSyncClient { /// /// The end-user verification code. /// The client Id. + /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ValidateDevice(string user_code, string client_id); + ClientResponse ValidateDevice(string user_code, string client_id, Guid? tenantId); /// /// Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly From f6f564e399dd938b3da41a0c2aa24292af78c7f0 Mon Sep 17 00:00:00 2001 From: Lyle Schemmerling Date: Tue, 23 Sep 2025 12:17:31 -0600 Subject: [PATCH 2/3] validate and libs --- .../src/io/fusionauth/FusionAuthClient.cs | 155 ++++++- .../src/io/fusionauth/FusionAuthSyncClient.cs | 109 ++++- .../src/io/fusionauth/IFusionAuthClient.cs | 417 ++++++++++++++++-- 3 files changed, 593 insertions(+), 88 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs index 6eb7a22f..b2d73a18 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs @@ -119,13 +119,12 @@ public Task> AddUserToFamilyAsync(Guid? familyId, } /// - public Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code, Guid? tenantId) { + public Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, { "token", token }, { "user_code", user_code }, - { "tenantId", tenantId }, }; return buildClient() .withUri("/oauth2/device/approve") @@ -134,6 +133,15 @@ public Task> ApproveDeviceAsync(string cl .goAsync(); } + /// + public Task> ApproveDeviceWithRequestAsync(DeviceApprovalRequest request) { + return buildClient() + .withUri("/oauth2/device/approve") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> CancelActionAsync(Guid? actionId, ActionRequest request) { return buildClient() @@ -212,13 +220,12 @@ public Task> CheckChangePasswordUsingLoginIdAsync(strin } /// - public Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope, Guid? tenantId) { + public Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, { "grant_type", "client_credentials" }, { "scope", scope }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -227,6 +234,15 @@ public Task> ClientCredentialsGrantAsync(string clie .goAsync(); } + /// + public Task> ClientCredentialsGrantWithRequestAsync(ClientCredentialsGrantRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/token") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> CommentOnUserAsync(UserCommentRequest request) { return buildClient() @@ -968,6 +984,29 @@ public Task> DeleteWebhookAsync(Guid? webhookId) { .goAsync(); } + /// + public Task> DeviceAuthorizeAsync(string client_id, string client_secret, string scope) { + var body = new Dictionary { + { "client_id", client_id }, + { "client_secret", client_secret }, + { "scope", scope }, + }; + return buildAnonymousClient() + .withUri("/oauth2/device_authorize") + .withFormData(new FormUrlEncodedContent(body)) + .withMethod("Post") + .goAsync(); + } + + /// + public Task> DeviceAuthorizeWithRequestAsync(DeviceAuthorizationRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/device_authorize") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> DisableTwoFactorAsync(Guid? userId, string methodId, string code) { return buildClient() @@ -1000,14 +1039,13 @@ public Task> EnableTwoFactorAsync(Guid? userId } /// - public Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId) { + public Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri) { var body = new Dictionary { { "code", code }, { "client_id", client_id }, { "client_secret", client_secret }, { "grant_type", "authorization_code" }, { "redirect_uri", redirect_uri }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1017,7 +1055,7 @@ public Task> ExchangeOAuthCodeForAccessTokenAsync(st } /// - public Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId) { + public Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier) { var body = new Dictionary { { "code", code }, { "client_id", client_id }, @@ -1025,7 +1063,6 @@ public Task> ExchangeOAuthCodeForAccessTokenUsingPKC { "grant_type", "authorization_code" }, { "redirect_uri", redirect_uri }, { "code_verifier", code_verifier }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1035,7 +1072,25 @@ public Task> ExchangeOAuthCodeForAccessTokenUsingPKC } /// - public Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { + public Task> ExchangeOAuthCodeForAccessTokenUsingPKCEWithRequestAsync(OAuthCodePKCEAccessTokenRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/token") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + + /// + public Task> ExchangeOAuthCodeForAccessTokenWithRequestAsync(OAuthCodeAccessTokenRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/token") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + + /// + public Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code) { var body = new Dictionary { { "refresh_token", refresh_token }, { "client_id", client_id }, @@ -1043,7 +1098,6 @@ public Task> ExchangeRefreshTokenForAccessTokenAsync { "grant_type", "refresh_token" }, { "scope", scope }, { "user_code", user_code }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1052,6 +1106,15 @@ public Task> ExchangeRefreshTokenForAccessTokenAsync .goAsync(); } + /// + public Task> ExchangeRefreshTokenForAccessTokenWithRequestAsync(RefreshTokenAccessTokenRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/token") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> ExchangeRefreshTokenForJWTAsync(RefreshRequest request) { return buildAnonymousClient() @@ -1062,7 +1125,7 @@ public Task> ExchangeRefreshTokenForJWTAsync( } /// - public Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { + public Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code) { var body = new Dictionary { { "username", username }, { "password", password }, @@ -1071,7 +1134,6 @@ public Task> ExchangeUserCredentialsForAccessTokenAs { "grant_type", "password" }, { "scope", scope }, { "user_code", user_code }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/token") @@ -1080,6 +1142,15 @@ public Task> ExchangeUserCredentialsForAccessTokenAs .goAsync(); } + /// + public Task> ExchangeUserCredentialsForAccessTokenWithRequestAsync(UserCredentialsAccessTokenRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/token") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> ForgotPasswordAsync(ForgotPasswordRequest request) { return buildClient() @@ -1193,11 +1264,10 @@ public Task> ImportWebAuthnCredentialAsync(WebAuthnCred } /// - public Task> IntrospectAccessTokenAsync(string client_id, string token, Guid? tenantId) { + public Task> IntrospectAccessTokenAsync(string client_id, string token) { var body = new Dictionary { { "client_id", client_id }, { "token", token }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/introspect") @@ -1207,10 +1277,18 @@ public Task> IntrospectAccessTokenAsync(strin } /// - public Task> IntrospectClientCredentialsAccessTokenAsync(string token, Guid? tenantId) { + public Task> IntrospectAccessTokenWithRequestAsync(AccessTokenIntrospectRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/introspect") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + + /// + public Task> IntrospectClientCredentialsAccessTokenAsync(string token) { var body = new Dictionary { { "token", token }, - { "tenantId", tenantId }, }; return buildAnonymousClient() .withUri("/oauth2/introspect") @@ -1219,6 +1297,15 @@ public Task> IntrospectClientCredentialsAcces .goAsync(); } + /// + public Task> IntrospectClientCredentialsAccessTokenWithRequestAsync(ClientCredentialsAccessTokenIntrospectRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/introspect") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> IssueJWTAsync(Guid? applicationId, string encodedJWT, string refreshToken) { return buildAnonymousClient() @@ -2515,7 +2602,7 @@ public Task> RetrieveUserByVerificationIdAsync(stri } /// - public Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code, Guid? tenantId) { + public Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code) { var body = new Dictionary { { "client_id", client_id }, { "client_secret", client_secret }, @@ -2523,25 +2610,41 @@ public Task> RetrieveUserCodeAsync(string client_id, st }; return buildAnonymousClient() .withUri("/oauth2/device/user-code") - .withParameter("tenantId", tenantId) .withFormData(new FormUrlEncodedContent(body)) .withMethod("Get") .goAsync(); } /// - public Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code, Guid? tenantId) { + public Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code) { var body = new Dictionary { { "user_code", user_code }, }; return buildAnonymousClient() .withUri("/oauth2/device/user-code") - .withParameter("tenantId", tenantId) .withFormData(new FormUrlEncodedContent(body)) .withMethod("Get") .goAsync(); } + /// + public Task> RetrieveUserCodeUsingAPIKeyWithRequestAsync(RetrieveUserCodeUsingAPIKeyRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/device/user-code") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + + /// + public Task> RetrieveUserCodeWithRequestAsync(RetrieveUserCodeRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/device/user-code") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> RetrieveUserCommentsAsync(Guid? userId) { return buildClient() @@ -3484,16 +3587,24 @@ public Task> UpsertEntityGrantAsync(Guid? entityId, Ent } /// - public Task> ValidateDeviceAsync(string user_code, string client_id, Guid? tenantId) { + public Task> ValidateDeviceAsync(string user_code, string client_id) { return buildAnonymousClient() .withUri("/oauth2/device/validate") .withParameter("user_code", user_code) .withParameter("client_id", client_id) - .withParameter("tenantId", tenantId) .withMethod("Get") .goAsync(); } + /// + public Task> ValidateDeviceWithRequestAsync(ValidateDeviceRequest request) { + return buildAnonymousClient() + .withUri("/oauth2/device/validate") + .withJSONBody(request) + .withMethod("Post") + .goAsync(); + } + /// public Task> ValidateJWTAsync(string encodedJWT) { return buildAnonymousClient() diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs index 130684fa..1e5fe9a2 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs @@ -72,8 +72,13 @@ public ClientResponse AddUserToFamily(Guid? familyId, FamilyRequ } /// - public ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code, Guid? tenantId) { - return client.ApproveDeviceAsync(client_id, client_secret, token, user_code, tenantId).GetAwaiter().GetResult(); + public ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code) { + return client.ApproveDeviceAsync(client_id, client_secret, token, user_code).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ApproveDeviceWithRequest(DeviceApprovalRequest request) { + return client.ApproveDeviceWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -118,8 +123,13 @@ public ClientResponse CheckChangePasswordUsingLoginId(string loginId) } /// - public ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope, Guid? tenantId) { - return client.ClientCredentialsGrantAsync(client_id, client_secret, scope, tenantId).GetAwaiter().GetResult(); + public ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope) { + return client.ClientCredentialsGrantAsync(client_id, client_secret, scope).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ClientCredentialsGrantWithRequest(ClientCredentialsGrantRequest request) { + return client.ClientCredentialsGrantWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -504,6 +514,16 @@ public ClientResponse DeleteWebhook(Guid? webhookId) { return client.DeleteWebhookAsync(webhookId).GetAwaiter().GetResult(); } + /// + public ClientResponse DeviceAuthorize(string client_id, string client_secret, string scope) { + return client.DeviceAuthorizeAsync(client_id, client_secret, scope).GetAwaiter().GetResult(); + } + + /// + public ClientResponse DeviceAuthorizeWithRequest(DeviceAuthorizationRequest request) { + return client.DeviceAuthorizeWithRequestAsync(request).GetAwaiter().GetResult(); + } + /// public ClientResponse DisableTwoFactor(Guid? userId, string methodId, string code) { return client.DisableTwoFactorAsync(userId, methodId, code).GetAwaiter().GetResult(); @@ -520,18 +540,33 @@ public ClientResponse EnableTwoFactor(Guid? userId, TwoFactor } /// - public ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId) { - return client.ExchangeOAuthCodeForAccessTokenAsync(code, client_id, client_secret, redirect_uri, tenantId).GetAwaiter().GetResult(); + public ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri) { + return client.ExchangeOAuthCodeForAccessTokenAsync(code, client_id, client_secret, redirect_uri).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier) { + return client.ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(code, client_id, client_secret, redirect_uri, code_verifier).GetAwaiter().GetResult(); } /// - public ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId) { - return client.ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(code, client_id, client_secret, redirect_uri, code_verifier, tenantId).GetAwaiter().GetResult(); + public ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCEWithRequest(OAuthCodePKCEAccessTokenRequest request) { + return client.ExchangeOAuthCodeForAccessTokenUsingPKCEWithRequestAsync(request).GetAwaiter().GetResult(); } /// - public ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { - return client.ExchangeRefreshTokenForAccessTokenAsync(refresh_token, client_id, client_secret, scope, user_code, tenantId).GetAwaiter().GetResult(); + public ClientResponse ExchangeOAuthCodeForAccessTokenWithRequest(OAuthCodeAccessTokenRequest request) { + return client.ExchangeOAuthCodeForAccessTokenWithRequestAsync(request).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code) { + return client.ExchangeRefreshTokenForAccessTokenAsync(refresh_token, client_id, client_secret, scope, user_code).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ExchangeRefreshTokenForAccessTokenWithRequest(RefreshTokenAccessTokenRequest request) { + return client.ExchangeRefreshTokenForAccessTokenWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -540,8 +575,13 @@ public ClientResponse ExchangeRefreshTokenForJWT(RefreshRequ } /// - public ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId) { - return client.ExchangeUserCredentialsForAccessTokenAsync(username, password, client_id, client_secret, scope, user_code, tenantId).GetAwaiter().GetResult(); + public ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code) { + return client.ExchangeUserCredentialsForAccessTokenAsync(username, password, client_id, client_secret, scope, user_code).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ExchangeUserCredentialsForAccessTokenWithRequest(UserCredentialsAccessTokenRequest request) { + return client.ExchangeUserCredentialsForAccessTokenWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -605,13 +645,23 @@ public ClientResponse ImportWebAuthnCredential(WebAuthnCredentialImpor } /// - public ClientResponse IntrospectAccessToken(string client_id, string token, Guid? tenantId) { - return client.IntrospectAccessTokenAsync(client_id, token, tenantId).GetAwaiter().GetResult(); + public ClientResponse IntrospectAccessToken(string client_id, string token) { + return client.IntrospectAccessTokenAsync(client_id, token).GetAwaiter().GetResult(); + } + + /// + public ClientResponse IntrospectAccessTokenWithRequest(AccessTokenIntrospectRequest request) { + return client.IntrospectAccessTokenWithRequestAsync(request).GetAwaiter().GetResult(); + } + + /// + public ClientResponse IntrospectClientCredentialsAccessToken(string token) { + return client.IntrospectClientCredentialsAccessTokenAsync(token).GetAwaiter().GetResult(); } /// - public ClientResponse IntrospectClientCredentialsAccessToken(string token, Guid? tenantId) { - return client.IntrospectClientCredentialsAccessTokenAsync(token, tenantId).GetAwaiter().GetResult(); + public ClientResponse IntrospectClientCredentialsAccessTokenWithRequest(ClientCredentialsAccessTokenIntrospectRequest request) { + return client.IntrospectClientCredentialsAccessTokenWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -1315,13 +1365,23 @@ public ClientResponse RetrieveUserByVerificationId(string verifica } /// - public ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code, Guid? tenantId) { - return client.RetrieveUserCodeAsync(client_id, client_secret, user_code, tenantId).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code) { + return client.RetrieveUserCodeAsync(client_id, client_secret, user_code).GetAwaiter().GetResult(); } /// - public ClientResponse RetrieveUserCodeUsingAPIKey(string user_code, Guid? tenantId) { - return client.RetrieveUserCodeUsingAPIKeyAsync(user_code, tenantId).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserCodeUsingAPIKey(string user_code) { + return client.RetrieveUserCodeUsingAPIKeyAsync(user_code).GetAwaiter().GetResult(); + } + + /// + public ClientResponse RetrieveUserCodeUsingAPIKeyWithRequest(RetrieveUserCodeUsingAPIKeyRequest request) { + return client.RetrieveUserCodeUsingAPIKeyWithRequestAsync(request).GetAwaiter().GetResult(); + } + + /// + public ClientResponse RetrieveUserCodeWithRequest(RetrieveUserCodeRequest request) { + return client.RetrieveUserCodeWithRequestAsync(request).GetAwaiter().GetResult(); } /// @@ -1819,8 +1879,13 @@ public ClientResponse UpsertEntityGrant(Guid? entityId, EntityGrantReq } /// - public ClientResponse ValidateDevice(string user_code, string client_id, Guid? tenantId) { - return client.ValidateDeviceAsync(user_code, client_id, tenantId).GetAwaiter().GetResult(); + public ClientResponse ValidateDevice(string user_code, string client_id) { + return client.ValidateDeviceAsync(user_code, client_id).GetAwaiter().GetResult(); + } + + /// + public ClientResponse ValidateDeviceWithRequest(ValidateDeviceRequest request) { + return client.ValidateDeviceWithRequestAsync(request).GetAwaiter().GetResult(); } /// diff --git a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs index 26ce754c..aaebfb48 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs @@ -84,14 +84,26 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The access token used to identify the user. /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code, Guid? tenantId); + Task> ApproveDeviceAsync(string client_id, string client_secret, string token, string user_code); + + /// + /// Approve a device grant. + /// This is an asynchronous method. + /// + /// The request object containing the device approval information and optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ApproveDeviceWithRequestAsync(DeviceApprovalRequest request); /// /// Cancels the user action. @@ -235,14 +247,26 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret used to authenticate this request. /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) This parameter is used to indicate which target entity you are requesting access. To request access to an entity, use the format target-entity:<target-entity-id>:<roles>. Roles are an optional comma separated list. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope, Guid? tenantId); + Task> ClientCredentialsGrantAsync(string client_id, string client_secret, string scope); + + /// + /// Make a Client Credentials grant request to obtain an access token. + /// This is an asynchronous method. + /// + /// The client credentials grant request containing client authentication, scope and optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ClientCredentialsGrantWithRequestAsync(ClientCredentialsGrantRequest request); /// /// Adds a comment to the user's account. @@ -1306,6 +1330,34 @@ public interface IFusionAuthAsyncClient { /// Task> DeleteWebhookAsync(Guid? webhookId); + /// + /// Start the Device Authorization flow using form-encoded parameters + /// This is an asynchronous method. + /// + /// The unique client identifier. The client Id is the Id of the FusionAuth Application in which you are attempting to authenticate. + /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. + /// (Optional) A space-delimited string of the requested scopes. Defaults to all scopes configured in the Application's OAuth configuration. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> DeviceAuthorizeAsync(string client_id, string client_secret, string scope); + + /// + /// Start the Device Authorization flow using a request body + /// This is an asynchronous method. + /// + /// The device authorization request containing client authentication, scope, and optional device metadata. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> DeviceAuthorizeWithRequestAsync(DeviceAuthorizationRequest request); + /// /// Disable two-factor authentication for a user. /// This is an asynchronous method. @@ -1359,14 +1411,13 @@ public interface IFusionAuthAsyncClient { /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The URI to redirect to upon a successful request. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId); + Task> ExchangeOAuthCodeForAccessTokenAsync(string code, string client_id, string client_secret, string redirect_uri); /// /// Exchanges an OAuth authorization code and code_verifier for an access token. @@ -1379,14 +1430,41 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// The URI to redirect to upon a successful request. /// The random string generated previously. Will be compared with the code_challenge sent previously, which allows the OAuth provider to authenticate your app. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId); + Task> ExchangeOAuthCodeForAccessTokenUsingPKCEAsync(string code, string client_id, string client_secret, string redirect_uri, string code_verifier); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The PKCE OAuth code access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ExchangeOAuthCodeForAccessTokenUsingPKCEWithRequestAsync(OAuthCodePKCEAccessTokenRequest request); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The OAuth code access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ExchangeOAuthCodeForAccessTokenWithRequestAsync(OAuthCodeAccessTokenRequest request); /// /// Exchange a Refresh Token for an Access Token. @@ -1399,14 +1477,27 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. - /// (Optional) The Id of the tenant to use for this request. Required if the request is for a universal application. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); + Task> ExchangeRefreshTokenForAccessTokenAsync(string refresh_token, string client_id, string client_secret, string scope, string user_code); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The refresh token access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ExchangeRefreshTokenForAccessTokenWithRequestAsync(RefreshTokenAccessTokenRequest request); /// /// Exchange a refresh token for a new JWT. @@ -1433,14 +1524,27 @@ public interface IFusionAuthAsyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); + Task> ExchangeUserCredentialsForAccessTokenAsync(string username, string password, string client_id, string client_secret, string scope, string user_code); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The user credentials access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ExchangeUserCredentialsForAccessTokenWithRequestAsync(UserCredentialsAccessTokenRequest request); /// /// Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. @@ -1628,28 +1732,52 @@ public interface IFusionAuthAsyncClient { /// /// The unique client identifier. The client Id is the Id of the FusionAuth Application for which this token was generated. /// The access token returned by this OAuth provider as the result of a successful client credentials grant. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> IntrospectAccessTokenAsync(string client_id, string token, Guid? tenantId); + Task> IntrospectAccessTokenAsync(string client_id, string token); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The access token introspection request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> IntrospectAccessTokenWithRequestAsync(AccessTokenIntrospectRequest request); /// /// Inspect an access token issued as the result of the Client Credentials Grant. /// This is an asynchronous method. /// /// The access token returned by this OAuth provider as the result of a successful client credentials grant. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> IntrospectClientCredentialsAccessTokenAsync(string token, Guid? tenantId); + Task> IntrospectClientCredentialsAccessTokenAsync(string token); + + /// + /// Inspect an access token issued as the result of the Client Credentials Grant. + /// This is an asynchronous method. + /// + /// The client credentials access token. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> IntrospectClientCredentialsAccessTokenWithRequestAsync(ClientCredentialsAccessTokenIntrospectRequest request); /// /// Issue a new access token (JWT) for the requested Application after ensuring the provided JWT is valid. A valid @@ -3563,14 +3691,13 @@ public interface IFusionAuthAsyncClient { /// The client Id. /// The client Id. /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code, Guid? tenantId); + Task> RetrieveUserCodeAsync(string client_id, string client_secret, string user_code); /// /// Retrieve a user_code that is part of an in-progress Device Authorization Grant. @@ -3581,14 +3708,45 @@ public interface IFusionAuthAsyncClient { /// This is an asynchronous method. /// /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code, Guid? tenantId); + Task> RetrieveUserCodeUsingAPIKeyAsync(string user_code); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The user code retrieval request including optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> RetrieveUserCodeUsingAPIKeyWithRequestAsync(RetrieveUserCodeUsingAPIKeyRequest request); + + /// + /// 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 is an asynchronous method. + /// + /// The user code retrieval request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> RetrieveUserCodeWithRequestAsync(RetrieveUserCodeRequest request); /// /// Retrieves all the comments for the user with the given Id. @@ -4964,14 +5122,27 @@ public interface IFusionAuthAsyncClient { /// /// The end-user verification code. /// The client Id. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> ValidateDeviceAsync(string user_code, string client_id, Guid? tenantId); + Task> ValidateDeviceAsync(string user_code, string client_id); + + /// + /// 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. + /// This is an asynchronous method. + /// + /// The device validation request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + Task> ValidateDeviceWithRequestAsync(ValidateDeviceRequest request); /// /// Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly @@ -5151,14 +5322,25 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The access token used to identify the user. /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code, Guid? tenantId); + ClientResponse ApproveDevice(string client_id, string client_secret, string token, string user_code); + + /// + /// Approve a device grant. + /// + /// The request object containing the device approval information and optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ApproveDeviceWithRequest(DeviceApprovalRequest request); /// /// Cancels the user action. @@ -5293,14 +5475,25 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret used to authenticate this request. /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) This parameter is used to indicate which target entity you are requesting access. To request access to an entity, use the format target-entity:<target-entity-id>:<roles>. Roles are an optional comma separated list. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope, Guid? tenantId); + ClientResponse ClientCredentialsGrant(string client_id, string client_secret, string scope); + + /// + /// Make a Client Credentials grant request to obtain an access token. + /// + /// The client credentials grant request containing client authentication, scope and optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ClientCredentialsGrantWithRequest(ClientCredentialsGrantRequest request); /// /// Adds a comment to the user's account. @@ -6288,6 +6481,32 @@ public interface IFusionAuthSyncClient { /// ClientResponse DeleteWebhook(Guid? webhookId); + /// + /// Start the Device Authorization flow using form-encoded parameters + /// + /// The unique client identifier. The client Id is the Id of the FusionAuth Application in which you are attempting to authenticate. + /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. + /// (Optional) A space-delimited string of the requested scopes. Defaults to all scopes configured in the Application's OAuth configuration. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse DeviceAuthorize(string client_id, string client_secret, string scope); + + /// + /// Start the Device Authorization flow using a request body + /// + /// The device authorization request containing client authentication, scope, and optional device metadata. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse DeviceAuthorizeWithRequest(DeviceAuthorizationRequest request); + /// /// Disable two-factor authentication for a user. /// @@ -6337,14 +6556,13 @@ public interface IFusionAuthSyncClient { /// This parameter is optional when Basic Authorization is used to authenticate this request. /// (Optional) The client secret. This value will be required if client authentication is enabled. /// The URI to redirect to upon a successful request. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri, Guid? tenantId); + ClientResponse ExchangeOAuthCodeForAccessToken(string code, string client_id, string client_secret, string redirect_uri); /// /// Exchanges an OAuth authorization code and code_verifier for an access token. @@ -6356,14 +6574,39 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// The URI to redirect to upon a successful request. /// The random string generated previously. Will be compared with the code_challenge sent previously, which allows the OAuth provider to authenticate your app. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier, Guid? tenantId); + ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCE(string code, string client_id, string client_secret, string redirect_uri, string code_verifier); + + /// + /// 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. + /// + /// The PKCE OAuth code access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ExchangeOAuthCodeForAccessTokenUsingPKCEWithRequest(OAuthCodePKCEAccessTokenRequest request); + + /// + /// 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. + /// + /// The OAuth code access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ExchangeOAuthCodeForAccessTokenWithRequest(OAuthCodeAccessTokenRequest request); /// /// Exchange a Refresh Token for an Access Token. @@ -6375,14 +6618,26 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. - /// (Optional) The Id of the tenant to use for this request. Required if the request is for a universal application. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); + ClientResponse ExchangeRefreshTokenForAccessToken(string refresh_token, string client_id, string client_secret, string scope, string user_code); + + /// + /// 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. + /// + /// The refresh token access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ExchangeRefreshTokenForAccessTokenWithRequest(RefreshTokenAccessTokenRequest request); /// /// Exchange a refresh token for a new JWT. @@ -6407,14 +6662,26 @@ public interface IFusionAuthSyncClient { /// (Optional) The client secret. This value may optionally be provided in the request body instead of the Authorization header. /// (Optional) This parameter is optional and if omitted, the same scope requested during the authorization request will be used. If provided the scopes must match those requested during the initial authorization request. /// (Optional) The end-user verification code. This code is required if using this endpoint to approve the Device Authorization. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code, Guid? tenantId); + ClientResponse ExchangeUserCredentialsForAccessToken(string username, string password, string client_id, string client_secret, string scope, string user_code); + + /// + /// 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. + /// + /// The user credentials access token exchange request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ExchangeUserCredentialsForAccessTokenWithRequest(UserCredentialsAccessTokenRequest request); /// /// Begins the forgot password sequence, which kicks off an email to the user so that they can reset their password. @@ -6589,27 +6856,49 @@ public interface IFusionAuthSyncClient { /// /// The unique client identifier. The client Id is the Id of the FusionAuth Application for which this token was generated. /// The access token returned by this OAuth provider as the result of a successful client credentials grant. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse IntrospectAccessToken(string client_id, string token, Guid? tenantId); + ClientResponse IntrospectAccessToken(string client_id, string token); + + /// + /// 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. + /// + /// The access token introspection request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse IntrospectAccessTokenWithRequest(AccessTokenIntrospectRequest request); /// /// Inspect an access token issued as the result of the Client Credentials Grant. /// /// The access token returned by this OAuth provider as the result of a successful client credentials grant. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse IntrospectClientCredentialsAccessToken(string token, Guid? tenantId); + ClientResponse IntrospectClientCredentialsAccessToken(string token); + + /// + /// Inspect an access token issued as the result of the Client Credentials Grant. + /// + /// The client credentials access token. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse IntrospectClientCredentialsAccessTokenWithRequest(ClientCredentialsAccessTokenIntrospectRequest request); /// /// Issue a new access token (JWT) for the requested Application after ensuring the provided JWT is valid. A valid @@ -8382,14 +8671,13 @@ public interface IFusionAuthSyncClient { /// The client Id. /// The client Id. /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code, Guid? tenantId); + ClientResponse RetrieveUserCode(string client_id, string client_secret, string user_code); /// /// Retrieve a user_code that is part of an in-progress Device Authorization Grant. @@ -8399,14 +8687,43 @@ public interface IFusionAuthSyncClient { /// This request will require an API key. /// /// The end-user verification code. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserCodeUsingAPIKey(string user_code, Guid? tenantId); + ClientResponse RetrieveUserCodeUsingAPIKey(string user_code); + + /// + /// 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. + /// + /// The user code retrieval request including optional tenantId. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse RetrieveUserCodeUsingAPIKeyWithRequest(RetrieveUserCodeUsingAPIKeyRequest request); + + /// + /// 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. + /// + /// The user code retrieval request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse RetrieveUserCodeWithRequest(RetrieveUserCodeRequest request); /// /// Retrieves all the comments for the user with the given Id. @@ -9683,14 +10000,26 @@ public interface IFusionAuthSyncClient { /// /// The end-user verification code. /// The client Id. - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse ValidateDevice(string user_code, string client_id, Guid? tenantId); + ClientResponse ValidateDevice(string user_code, string client_id); + + /// + /// 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. + /// + /// The device validation request. + /// + /// When successful, the response will contain the log of the action. If there was a validation error or any + /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be + /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an + /// IOException. + /// + ClientResponse ValidateDeviceWithRequest(ValidateDeviceRequest request); /// /// Validates the provided JWT (encoded JWT string) to ensure the token is valid. A valid access token is properly From 86355a5260a147d773e7dc3082a5d28bad02a29b Mon Sep 17 00:00:00 2001 From: Lyle Schemmerling Date: Tue, 23 Sep 2025 12:42:53 -0600 Subject: [PATCH 3/3] fix imports and user info --- .../src/io/fusionauth/FusionAuthClient.cs | 3 +-- .../src/io/fusionauth/FusionAuthSyncClient.cs | 4 ++-- .../src/io/fusionauth/IFusionAuthClient.cs | 6 ++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs index b2d73a18..28a7ff69 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs @@ -2673,11 +2673,10 @@ public Task> RetrieveUserConsentsAsync(Guid? } /// - public Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT, Guid? tenantId) { + public Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT) { return buildAnonymousClient() .withUri("/oauth2/userinfo") .withAuthorization("Bearer " + encodedJWT) - .withParameter("tenantId", tenantId) .withMethod("Get") .goAsync(); } diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs index 1e5fe9a2..66406b89 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs @@ -1400,8 +1400,8 @@ public ClientResponse RetrieveUserConsents(Guid? userId) { } /// - public ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT, Guid? tenantId) { - return client.RetrieveUserInfoFromAccessTokenAsync(encodedJWT, tenantId).GetAwaiter().GetResult(); + public ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT) { + return client.RetrieveUserInfoFromAccessTokenAsync(encodedJWT).GetAwaiter().GetResult(); } /// diff --git a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs index aaebfb48..d2165cae 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/IFusionAuthClient.cs @@ -3792,14 +3792,13 @@ public interface IFusionAuthAsyncClient { /// This is an asynchronous method. /// /// The encoded JWT (access token). - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT, Guid? tenantId); + Task> RetrieveUserInfoFromAccessTokenAsync(string encodedJWT); /// /// Retrieve a single Identity Provider user (link). @@ -8765,14 +8764,13 @@ public interface IFusionAuthSyncClient { /// Call the UserInfo endpoint to retrieve User Claims from the access token issued by FusionAuth. /// /// The encoded JWT (access token). - /// (Optional) The Id of the tenant to use for this request. /// /// When successful, the response will contain the log of the action. If there was a validation error or any /// other type of error, this will return the Errors object in the response. Additionally, if FusionAuth could not be /// contacted because it is down or experiencing a failure, the response will contain an Exception, which could be an /// IOException. /// - ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT, Guid? tenantId); + ClientResponse RetrieveUserInfoFromAccessToken(string encodedJWT); /// /// Retrieve a single Identity Provider user (link).