diff --git a/.fernignore b/.fernignore index 07cfccb12..86084f00c 100644 --- a/.fernignore +++ b/.fernignore @@ -46,3 +46,8 @@ src/Auth0.ManagementApi/Types/ResourceServerTokenEncryptionKey.cs src/Auth0.ManagementApi/Wrapper src/Auth0.ManagementApi/CHANGELOG.md + +src/Auth0.ManagementApi/Core/CustomDomainInterceptor.cs +src/Auth0.ManagementApi/CustomDomainHeader.cs +tests/Auth0.ManagementApi.Test/Core/CustomDomainInterceptorTest.cs +tests/Auth0.ManagementApi.Test/Unit/MockServer/CustomDomainHeaderTest.cs diff --git a/Examples.md b/Examples.md index 2164f2566..d9504e2d2 100644 --- a/Examples.md +++ b/Examples.md @@ -202,9 +202,10 @@ await authClient.DeleteMfaAuthenticatorAsync( - [4.3 Get a specific Network ACL configuration](#43-get-a-specific-network-acl-configuration) - [4.4 Update Network ACL with a PATCH request](#44-update-network-acl-with-a-patch-request) - [4.5 Update Network ACL with a PUT request](#45-update-network-acl-with-a-put-request) -- [5. Using a Custom Domain with the Management API](#5-using-a-custom-domain-with-the-management-api) - - [5.1 Let the client manage the connection (simplest)](#51-let-the-client-manage-the-connection-simplest) - - [5.2 Bring your own connection](#52-bring-your-own-connection) +- [5. Multiple Custom Domain (MCD) Header](#5-multiple-custom-domain-mcd-header) + - [5.1 Global configuration via ManagementClient (recommended)](#51-global-configuration-via-managementclient-recommended) + - [5.2 Per-request override](#52-per-request-override) + - [5.3 Global configuration via ManagementApiClient](#53-global-configuration-via-managementapiclient) ## 1. Management Client Initialization @@ -566,3 +567,148 @@ public async Task SetNetworkAcl(string aclId) ``` [Go to Top](#) + +## 5. Multiple Custom Domain (MCD) Header + +Auth0 tenants with Multiple Custom Domains enabled must supply the `Auth0-Custom-Domain` header +on the Management API endpoints that generate user-facing links. The affected endpoints are: + +- `POST /api/v2/tickets/email-verification` +- `POST /api/v2/tickets/password-change` +- `POST /api/v2/organizations/{id}/invitations` +- `POST /api/v2/guardian/enrollments/ticket` +- `POST /api/v2/jobs/verification-email` +- `POST /api/v2/jobs/users-imports` (when `verify_email: true`) +- `POST /api/v2/users` (Create) +- `PATCH /api/v2/users/{id}` (Update, when `verify_email: true`) + +### 5.1 Global configuration via ManagementClient (recommended) + +When `CustomDomain` is set on `ManagementClientOptions` and no custom `HttpClient` is provided, +the SDK automatically configures a `CustomDomainInterceptor` that strips the header from any +endpoint not on the whitelist above. + +```csharp +using Auth0.ManagementApi; + +public async Task UseCustomDomainGlobal() +{ + var client = new ManagementClient(new ManagementClientOptions + { + Domain = "my.auth0.domain", + TokenProvider = new ClientCredentialsTokenProvider( + domain: "my.auth0.domain", + clientId: "clientId", + clientSecret: "clientSecret" + ), + CustomDomain = "login.mycompany.com" + }); + + // Auth0-Custom-Domain header is sent automatically on whitelisted endpoints + // and stripped from all others. + var ticket = await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|abc123" }); + + Console.WriteLine($"Ticket URL: {ticket.Ticket}"); +} +``` + +[Go to Top](#) + +### 5.2 Per-request override + +Use `CustomDomainHeader.For()` to supply the header for a single call without configuring it +globally. This is useful when only a subset of calls require the header, or when you need to +use a different domain for a specific request. + +```csharp +using Auth0.ManagementApi; + +public async Task UseCustomDomainPerRequest() +{ + // Client without a global custom domain + var client = new ManagementClient(new ManagementClientOptions + { + Domain = "my.auth0.domain", + TokenProvider = new ClientCredentialsTokenProvider( + domain: "my.auth0.domain", + clientId: "clientId", + clientSecret: "clientSecret" + ) + }); + + // Supply the header only for this call + var ticket = await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|abc123" }, + CustomDomainHeader.For("login.mycompany.com")); + + Console.WriteLine($"Ticket URL: {ticket.Ticket}"); + + // Works with any whitelisted endpoint + var invitation = await client.Organizations.Invitations.CreateAsync( + "org_123", + new CreateOrganizationInvitationRequestContent + { + Inviter = new OrganizationInvitationInviter { Name = "Admin" }, + Invitee = new OrganizationInvitationInvitee { Email = "user@example.com" }, + ClientId = "clientId" + }, + CustomDomainHeader.For("login.mycompany.com")); +} +``` + +> **Combining with other per-request options:** `CustomDomainHeader.For()` is a convenience +> helper that returns a `RequestOptions` pre-populated with only the `Auth0-Custom-Domain` +> header. When you also need to set other options on the same call (additional headers, timeout, +> retries), construct `RequestOptions` directly instead: +> +> ```csharp +> await client.Tickets.VerifyEmailAsync( +> new VerifyEmailTicketRequestContent { UserId = "auth0|abc123" }, +> new RequestOptions +> { +> AdditionalHeaders = new[] +> { +> new KeyValuePair("Auth0-Custom-Domain", "login.mycompany.com"), +> new KeyValuePair("X-Correlation-Id", "abc-123"), +> }, +> MaxRetries = 1, +> }); +> ``` + +[Go to Top](#) + +### 5.3 Global configuration via ManagementApiClient + +If you manage tokens yourself using `ManagementApiClient` directly, pass a `CustomDomainInterceptor` +as the `HttpClient` handler to enable automatic header stripping. + +```csharp +using Auth0.ManagementApi; +using Auth0.ManagementApi.Core; + +public async Task UseCustomDomainWithManagementApiClient() +{ + // CustomDomainInterceptor strips the header from non-whitelisted endpoints. + var client = new ManagementApiClient( + token: "your-access-token", + clientOptions: new ClientOptions + { + BaseUrl = "https://my.auth0.domain/api/v2", + CustomDomain = "login.mycompany.com", + HttpClient = new HttpClient(new CustomDomainInterceptor()) + }); + + var ticket = await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|abc123" }); + + Console.WriteLine($"Ticket URL: {ticket.Ticket}"); +} +``` + +> **Note:** If you supply your own `HttpClient` alongside `CustomDomain`, the +> `CustomDomainInterceptor` is **not** injected automatically — you must add it yourself +> as shown above. Without it the header is still sent, but it will be present on every +> request rather than only whitelisted ones. + +[Go to Top](#) diff --git a/reference.md b/reference.md index 36a538000..c56538697 100644 --- a/reference.md +++ b/reference.md @@ -558,6 +558,7 @@ await client.ClientGrants.ListAsync( ClientId = "client_id", AllowAnyOrganization = true, SubjectType = ClientGrantSubjectTypeEnum.Client, + DefaultFor = ClientGrantDefaultForEnum.ThirdPartyClients, } ); ``` @@ -3346,7 +3347,7 @@ await client.EventStreams.TestAsync( "id", new CreateEventStreamTestEventRequestContent { - EventType = EventStreamTestEventTypeEnum.UserCreated, + EventType = EventStreamTestEventTypeEnum.GroupCreated, } ); ``` @@ -4553,72 +4554,77 @@ await client.Jobs.GetAsync("id");
-Retrieve details on log streams. -
Sample Response
[{
-	"id": "string",
-	"name": "string",
-	"type": "eventbridge",
-	"status": "active|paused|suspended",
-	"sink": {
-		"awsAccountId": "string",
-		"awsRegion": "string",
-		"awsPartnerEventSource": "string"
-	}
+Retrieve details on [log streams](https://auth0.com/docs/logs/streams).
+
+**Sample Response**
+
+```json
+[{
+  "id": "string",
+  "name": "string",
+  "type": "eventbridge",
+  "status": "active|paused|suspended",
+  "sink": {
+    "awsAccountId": "string",
+    "awsRegion": "string",
+    "awsPartnerEventSource": "string"
+  }
 }, {
-	"id": "string",
-	"name": "string",
-	"type": "http",
-	"status": "active|paused|suspended",
-	"sink": {
-		"httpContentFormat": "JSONLINES|JSONARRAY",
-		"httpContentType": "string",
-		"httpEndpoint": "string",
-		"httpAuthorization": "string"
-	}
+  "id": "string",
+  "name": "string",
+  "type": "http",
+  "status": "active|paused|suspended",
+  "sink": {
+    "httpContentFormat": "JSONLINES|JSONARRAY",
+    "httpContentType": "string",
+    "httpEndpoint": "string",
+    "httpAuthorization": "string"
+  }
 },
 {
-	"id": "string",
-	"name": "string",
-	"type": "eventgrid",
-	"status": "active|paused|suspended",
-	"sink": {
-		"azureSubscriptionId": "string",
-		"azureResourceGroup": "string",
-		"azureRegion": "string",
-		"azurePartnerTopic": "string"
-	}
+  "id": "string",
+  "name": "string",
+  "type": "eventgrid",
+  "status": "active|paused|suspended",
+  "sink": {
+    "azureSubscriptionId": "string",
+    "azureResourceGroup": "string",
+    "azureRegion": "string",
+    "azurePartnerTopic": "string"
+  }
 },
 {
-	"id": "string",
-	"name": "string",
-	"type": "splunk",
-	"status": "active|paused|suspended",
-	"sink": {
-		"splunkDomain": "string",
-		"splunkToken": "string",
-		"splunkPort": "string",
-		"splunkSecure": "boolean"
-	}
+  "id": "string",
+  "name": "string",
+  "type": "splunk",
+  "status": "active|paused|suspended",
+  "sink": {
+    "splunkDomain": "string",
+    "splunkToken": "string",
+    "splunkPort": "string",
+    "splunkSecure": "boolean"
+  }
 },
 {
-	"id": "string",
-	"name": "string",
-	"type": "sumo",
-	"status": "active|paused|suspended",
-	"sink": {
-		"sumoSourceAddress": "string",
-	}
+  "id": "string",
+  "name": "string",
+  "type": "sumo",
+  "status": "active|paused|suspended",
+  "sink": {
+    "sumoSourceAddress": "string"
+  }
 },
 {
-	"id": "string",
-	"name": "string",
-	"type": "datadog",
-	"status": "active|paused|suspended",
-	"sink": {
-		"datadogRegion": "string",
-		"datadogApiKey": "string"
-	}
-}]
+ "id": "string", + "name": "string", + "type": "datadog", + "status": "active|paused|suspended", + "sink": { + "datadogRegion": "string", + "datadogApiKey": "string" + } +}] +```
@@ -4658,131 +4664,202 @@ await client.LogStreams.ListAsync();
Create a log stream. -
Log Stream Types
The type of log stream being created determines the properties required in the sink payload. -
HTTP Stream
For an http Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "http",
-	"sink": {
-		"httpEndpoint": "string",
-		"httpContentType": "string",
-		"httpContentFormat": "JSONLINES|JSONARRAY",
-		"httpAuthorization": "string"
-	}
-}
-Response:
{
-	"id": "string",
-	"name": "string",
-	"type": "http",
-	"status": "active",
-	"sink": {
-		"httpEndpoint": "string",
-		"httpContentType": "string",
-		"httpContentFormat": "JSONLINES|JSONARRAY",
-		"httpAuthorization": "string"
-	}
-}
-
Amazon EventBridge Stream
For an eventbridge Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "eventbridge",
-	"sink": {
-		"awsRegion": "string",
-		"awsAccountId": "string"
-	}
-}
-The response will include an additional field awsPartnerEventSource in the sink:
{
-	"id": "string",
-	"name": "string",
-	"type": "eventbridge",
-	"status": "active",
-	"sink": {
-		"awsAccountId": "string",
-		"awsRegion": "string",
-		"awsPartnerEventSource": "string"
-	}
-}
-
Azure Event Grid Stream
For an Azure Event Grid Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "eventgrid",
-	"sink": {
-		"azureSubscriptionId": "string",
-		"azureResourceGroup": "string",
-		"azureRegion": "string"
-	}
-}
-Response:
{
-	"id": "string",
-	"name": "string",
-	"type": "http",
-	"status": "active",
-	"sink": {
-		"azureSubscriptionId": "string",
-		"azureResourceGroup": "string",
-		"azureRegion": "string",
-		"azurePartnerTopic": "string"
-	}
-}
-
Datadog Stream
For a Datadog Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "datadog",
-	"sink": {
-		"datadogRegion": "string",
-		"datadogApiKey": "string"
-	}
-}
-Response:
{
-	"id": "string",
-	"name": "string",
-	"type": "datadog",
-	"status": "active",
-	"sink": {
-		"datadogRegion": "string",
-		"datadogApiKey": "string"
-	}
-}
-
Splunk Stream
For a Splunk Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "splunk",
-	"sink": {
-		"splunkDomain": "string",
-		"splunkToken": "string",
-		"splunkPort": "string",
-		"splunkSecure": "boolean"
-	}
-}
-Response:
{
-	"id": "string",
-	"name": "string",
-	"type": "splunk",
-	"status": "active",
-	"sink": {
-		"splunkDomain": "string",
-		"splunkToken": "string",
-		"splunkPort": "string",
-		"splunkSecure": "boolean"
-	}
-}
-
Sumo Logic Stream
For a Sumo Logic Stream, the sink properties are listed in the payload below -Request:
{
-	"name": "string",
-	"type": "sumo",
-	"sink": {
-		"sumoSourceAddress": "string",
-	}
-}
-Response:
{
-	"id": "string",
-	"name": "string",
-	"type": "sumo",
-	"status": "active",
-	"sink": {
-		"sumoSourceAddress": "string",
-	}
-}
+ +**Log Stream Types** + +The `type` of log stream being created determines the properties required in the `sink` payload. + +**HTTP Stream** + +For an `http` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "http", + "sink": { + "httpEndpoint": "string", + "httpContentType": "string", + "httpContentFormat": "JSONLINES|JSONARRAY", + "httpAuthorization": "string" + } +} +``` + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "http", + "status": "active", + "sink": { + "httpEndpoint": "string", + "httpContentType": "string", + "httpContentFormat": "JSONLINES|JSONARRAY", + "httpAuthorization": "string" + } +} +``` + +**Amazon EventBridge Stream** + +For an `eventbridge` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "eventbridge", + "sink": { + "awsRegion": "string", + "awsAccountId": "string" + } +} +``` + +The response will include an additional field `awsPartnerEventSource` in the `sink`: + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "eventbridge", + "status": "active", + "sink": { + "awsAccountId": "string", + "awsRegion": "string", + "awsPartnerEventSource": "string" + } +} +``` + +**Azure Event Grid Stream** + +For an `Azure Event Grid` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "eventgrid", + "sink": { + "azureSubscriptionId": "string", + "azureResourceGroup": "string", + "azureRegion": "string" + } +} +``` + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "http", + "status": "active", + "sink": { + "azureSubscriptionId": "string", + "azureResourceGroup": "string", + "azureRegion": "string", + "azurePartnerTopic": "string" + } +} +``` + +**Datadog Stream** + +For a `Datadog` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "datadog", + "sink": { + "datadogRegion": "string", + "datadogApiKey": "string" + } +} +``` + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "datadog", + "status": "active", + "sink": { + "datadogRegion": "string", + "datadogApiKey": "string" + } +} +``` + +**Splunk Stream** + +For a `Splunk` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "splunk", + "sink": { + "splunkDomain": "string", + "splunkToken": "string", + "splunkPort": "string", + "splunkSecure": "boolean" + } +} +``` + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "splunk", + "status": "active", + "sink": { + "splunkDomain": "string", + "splunkToken": "string", + "splunkPort": "string", + "splunkSecure": "boolean" + } +} +``` + +**Sumo Logic Stream** + +For a `Sumo Logic` Stream, the `sink` properties are listed in the payload below. + +**Request:** +```json +{ + "name": "string", + "type": "sumo", + "sink": { + "sumoSourceAddress": "string" + } +} +``` + +**Response:** +```json +{ + "id": "string", + "name": "string", + "type": "sumo", + "status": "active", + "sink": { + "sumoSourceAddress": "string" + } +} +```
@@ -4843,107 +4920,157 @@ await client.LogStreams.CreateAsync(
Retrieve a log stream configuration and status. -
Sample responses
Amazon EventBridge Log Stream
{
-	"id": "string",
-	"name": "string",
-	"type": "eventbridge",
-	"status": "active|paused|suspended",
-	"sink": {
-		"awsAccountId": "string",
-		"awsRegion": "string",
-		"awsPartnerEventSource": "string"
-	}
-}
HTTP Log Stream
{
-	"id": "string",
-	"name": "string",
-	"type": "http",
-	"status": "active|paused|suspended",
-	"sink": {
-		"httpContentFormat": "JSONLINES|JSONARRAY",
-		"httpContentType": "string",
-		"httpEndpoint": "string",
-		"httpAuthorization": "string"
-	}
-}
Datadog Log Stream
{
-	"id": "string",
-	"name": "string",
-	"type": "datadog",
-	"status": "active|paused|suspended",
-	"sink": {
-		"datadogRegion": "string",
-		"datadogApiKey": "string"
-	}
-
-}
Mixpanel
- - Request:
{
-	  "name": "string",
-	  "type": "mixpanel",
-	  "sink": {
-		"mixpanelRegion": "string", // "us" | "eu",
-		"mixpanelProjectId": "string",
-		"mixpanelServiceAccountUsername": "string",
-		"mixpanelServiceAccountPassword": "string"
-	  }
-	} 
- - - Response:
{
-		"id": "string",
-		"name": "string",
-		"type": "mixpanel",
-		"status": "active",
-		"sink": {
-		  "mixpanelRegion": "string", // "us" | "eu",
-		  "mixpanelProjectId": "string",
-		  "mixpanelServiceAccountUsername": "string",
-		  "mixpanelServiceAccountPassword": "string" // the following is redacted on return
-		}
-	  } 
- -
Segment
- - Request:
 {
-	  "name": "string",
-	  "type": "segment",
-	  "sink": {
-		"segmentWriteKey": "string"
-	  }
-	}
- - Response:
{
-	  "id": "string",
-	  "name": "string",
-	  "type": "segment",
-	  "status": "active",
-	  "sink": {
-		"segmentWriteKey": "string"
-	  }
-	} 
- -
Splunk Log Stream
{
-	"id": "string",
-	"name": "string",
-	"type": "splunk",
-	"status": "active|paused|suspended",
-	"sink": {
-		"splunkDomain": "string",
-		"splunkToken": "string",
-		"splunkPort": "string",
-		"splunkSecure": "boolean"
-	}
-}
Sumo Logic Log Stream
{
-	"id": "string",
-	"name": "string",
-	"type": "sumo",
-	"status": "active|paused|suspended",
-	"sink": {
-		"sumoSourceAddress": "string",
-	}
-}
Status
The status of a log stream maybe any of the following: -1. active - Stream is currently enabled. -2. paused - Stream is currently user disabled and will not attempt log delivery. -3. suspended - Stream is currently disabled because of errors and will not attempt log delivery. + +**Sample responses** + +**Amazon EventBridge Log Stream** + +```json +{ + "id": "string", + "name": "string", + "type": "eventbridge", + "status": "active|paused|suspended", + "sink": { + "awsAccountId": "string", + "awsRegion": "string", + "awsPartnerEventSource": "string" + } +} +``` + +**HTTP Log Stream** + +```json +{ + "id": "string", + "name": "string", + "type": "http", + "status": "active|paused|suspended", + "sink": { + "httpContentFormat": "JSONLINES|JSONARRAY", + "httpContentType": "string", + "httpEndpoint": "string", + "httpAuthorization": "string" + } +} +``` + +**Datadog Log Stream** + +```json +{ + "id": "string", + "name": "string", + "type": "datadog", + "status": "active|paused|suspended", + "sink": { + "datadogRegion": "string", + "datadogApiKey": "string" + } +} +``` + +**Mixpanel** + +**Request:** + +```json +{ + "name": "string", + "type": "mixpanel", + "sink": { + "mixpanelRegion": "string", + "mixpanelProjectId": "string", + "mixpanelServiceAccountUsername": "string", + "mixpanelServiceAccountPassword": "string" + } +} +``` + +**Response:** + +```json +{ + "id": "string", + "name": "string", + "type": "mixpanel", + "status": "active", + "sink": { + "mixpanelRegion": "string", + "mixpanelProjectId": "string", + "mixpanelServiceAccountUsername": "string", + "mixpanelServiceAccountPassword": "string" + } +} +``` + +**Segment** + +**Request:** + +```json +{ + "name": "string", + "type": "segment", + "sink": { + "segmentWriteKey": "string" + } +} +``` + +**Response:** + +```json +{ + "id": "string", + "name": "string", + "type": "segment", + "status": "active", + "sink": { + "segmentWriteKey": "string" + } +} +``` + +**Splunk Log Stream** + +```json +{ + "id": "string", + "name": "string", + "type": "splunk", + "status": "active|paused|suspended", + "sink": { + "splunkDomain": "string", + "splunkToken": "string", + "splunkPort": "string", + "splunkSecure": "boolean" + } +} +``` + +**Sumo Logic Log Stream** + +```json +{ + "id": "string", + "name": "string", + "type": "sumo", + "status": "active|paused|suspended", + "sink": { + "sumoSourceAddress": "string" + } +} +``` + +**Status** + +The `status` of a log stream maybe any of the following: + +1. `active` - Stream is currently enabled. +2. `paused` - Stream is currently user disabled and will not attempt log delivery. +3. `suspended` - Stream is currently disabled because of errors and will not attempt log delivery.
@@ -5052,40 +5179,79 @@ await client.LogStreams.DeleteAsync("id");
Update a log stream. -

Examples of how to use the PATCH endpoint.

The following fields may be updated in a PATCH operation:
  • name
  • status
  • sink
Note: For log streams of type eventbridge and eventgrid, updating the sink is not permitted. -
Update the status of a log stream
{
-	"status": "active|paused"
-}
-
Update the name of a log stream
{
-	"name": "string"
-}
-
Update the sink properties of a stream of type http
{
+
+**Examples of how to use the PATCH endpoint.**
+
+The following fields may be updated in a PATCH operation:
+
+- name
+- status
+- sink
+
+Note: For log streams of type `eventbridge` and `eventgrid`, updating the `sink` is not permitted.
+
+**Update the status of a log stream**
+
+```json
+{
+  "status": "active|paused"
+}
+```
+
+**Update the name of a log stream**
+
+```json
+{
+  "name": "string"
+}
+```
+
+**Update the sink properties of a stream of type `http`**
+
+```json
+{
   "sink": {
     "httpEndpoint": "string",
     "httpContentType": "string",
     "httpContentFormat": "JSONARRAY|JSONLINES",
     "httpAuthorization": "string"
   }
-}
-
Update the sink properties of a stream of type datadog
{
+}
+```
+
+**Update the sink properties of a stream of type `datadog`**
+
+```json
+{
   "sink": {
-		"datadogRegion": "string",
-		"datadogApiKey": "string"
+    "datadogRegion": "string",
+    "datadogApiKey": "string"
   }
-}
-
Update the sink properties of a stream of type splunk
{
+}
+```
+
+**Update the sink properties of a stream of type `splunk`**
+
+```json
+{
   "sink": {
     "splunkDomain": "string",
     "splunkToken": "string",
     "splunkPort": "string",
     "splunkSecure": "boolean"
   }
-}
-
Update the sink properties of a stream of type sumo
{
+}
+```
+
+**Update the sink properties of a stream of type `sumo`**
+
+```json
+{
   "sink": {
     "sumoSourceAddress": "string"
   }
-}
+} +```
@@ -13341,6 +13507,142 @@ await client.Connections.DirectoryProvisioning.GetDefaultMappingAsync("id"); + + + + +
client.Connections.DirectoryProvisioning.ListSynchronizedGroupsAsync(id, ListSynchronizedGroupsRequestParameters { ... }) -> Pager<SynchronizedGroupPayload> +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve the configured synchronized groups for a connection directory provisioning configuration. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```csharp +await client.Connections.DirectoryProvisioning.ListSynchronizedGroupsAsync( + "id", + new ListSynchronizedGroupsRequestParameters { From = "from", Take = 1 } +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `string` — The id of the connection to list synchronized groups for. + +
+
+ +
+
+ +**request:** `ListSynchronizedGroupsRequestParameters` + +
+
+
+
+ + +
+
+
+ +
client.Connections.DirectoryProvisioning.SetAsync(id, ReplaceSynchronizedGroupsRequestContent { ... }) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create or replace the selected groups for a connection directory provisioning configuration. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```csharp +await client.Connections.DirectoryProvisioning.SetAsync( + "id", + new ReplaceSynchronizedGroupsRequestContent + { + Groups = new List() + { + new SynchronizedGroupPayload { Id = "id" }, + }, + } +); +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `string` — The id of the connection to create or replace synchronized groups for + +
+
+ +
+
+ +**request:** `ReplaceSynchronizedGroupsRequestContent` + +
+
+
+
+ +
diff --git a/src/Auth0.ManagementApi/ClientGrants/ClientGrantsClient.cs b/src/Auth0.ManagementApi/ClientGrants/ClientGrantsClient.cs index 8fadfa5e7..3138acb5c 100644 --- a/src/Auth0.ManagementApi/ClientGrants/ClientGrantsClient.cs +++ b/src/Auth0.ManagementApi/ClientGrants/ClientGrantsClient.cs @@ -37,7 +37,7 @@ private async Task< CancellationToken cancellationToken = default ) { - var _queryString = new Auth0.ManagementApi.Core.QueryStringBuilder.Builder(capacity: 6) + var _queryString = new Auth0.ManagementApi.Core.QueryStringBuilder.Builder(capacity: 7) .Add("from", request.From.IsDefined ? request.From.Value : null) .Add("take", request.Take.IsDefined ? request.Take.Value : null) .Add("audience", request.Audience.IsDefined ? request.Audience.Value : null) @@ -47,6 +47,7 @@ private async Task< request.AllowAnyOrganization.IsDefined ? request.AllowAnyOrganization.Value : null ) .Add("subject_type", request.SubjectType.IsDefined ? request.SubjectType.Value : null) + .Add("default_for", request.DefaultFor.IsDefined ? request.DefaultFor.Value : null) .MergeAdditional(options?.AdditionalQueryParameters) .Build(); var _headers = await new Auth0.ManagementApi.Core.HeadersBuilder.Builder() @@ -412,6 +413,7 @@ private async Task> UpdateAsyn /// ClientId = "client_id", /// AllowAnyOrganization = true, /// SubjectType = ClientGrantSubjectTypeEnum.Client, + /// DefaultFor = ClientGrantDefaultForEnum.ThirdPartyClients, /// } /// ); /// diff --git a/src/Auth0.ManagementApi/ClientGrants/Requests/CreateClientGrantRequestContent.cs b/src/Auth0.ManagementApi/ClientGrants/Requests/CreateClientGrantRequestContent.cs index e163f1df5..688befd93 100644 --- a/src/Auth0.ManagementApi/ClientGrants/Requests/CreateClientGrantRequestContent.cs +++ b/src/Auth0.ManagementApi/ClientGrants/Requests/CreateClientGrantRequestContent.cs @@ -19,6 +19,10 @@ public record CreateClientGrantRequestContent [JsonPropertyName("audience")] public required string Audience { get; set; } + [Optional] + [JsonPropertyName("default_for")] + public ClientGrantDefaultForEnum? DefaultFor { get; set; } + [Optional] [JsonPropertyName("organization_usage")] public ClientGrantOrganizationUsageEnum? OrganizationUsage { get; set; } diff --git a/src/Auth0.ManagementApi/ClientGrants/Requests/ListClientGrantsRequestParameters.cs b/src/Auth0.ManagementApi/ClientGrants/Requests/ListClientGrantsRequestParameters.cs index b47e1ff86..d60e93160 100644 --- a/src/Auth0.ManagementApi/ClientGrants/Requests/ListClientGrantsRequestParameters.cs +++ b/src/Auth0.ManagementApi/ClientGrants/Requests/ListClientGrantsRequestParameters.cs @@ -42,6 +42,12 @@ public record ListClientGrantsRequestParameters [JsonIgnore] public Optional SubjectType { get; set; } + /// + /// Applies this client grant as the default for all clients in the specified group. The only accepted value is `third_party_clients`, which applies the grant to all third-party clients. Per-client grants for the same audience take precedence. Mutually exclusive with `client_id`. + /// + [JsonIgnore] + public Optional DefaultFor { get; set; } + /// public override string ToString() { diff --git a/src/Auth0.ManagementApi/Clients/Requests/CreateClientRequestContent.cs b/src/Auth0.ManagementApi/Clients/Requests/CreateClientRequestContent.cs index d16de2620..2888d7491 100644 --- a/src/Auth0.ManagementApi/Clients/Requests/CreateClientRequestContent.cs +++ b/src/Auth0.ManagementApi/Clients/Requests/CreateClientRequestContent.cs @@ -286,10 +286,22 @@ public record CreateClientRequestContent [JsonPropertyName("resource_server_identifier")] public string? ResourceServerIdentifier { get; set; } + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + [Optional] [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationPostConfiguration? MyOrganizationConfiguration { get; set; } + [Optional] [JsonPropertyName("async_approval_notification_channels")] public IEnumerable? AsyncApprovalNotificationChannels { get; set; } diff --git a/src/Auth0.ManagementApi/Clients/Requests/UpdateClientRequestContent.cs b/src/Auth0.ManagementApi/Clients/Requests/UpdateClientRequestContent.cs index e77075b62..34b5b7b80 100644 --- a/src/Auth0.ManagementApi/Clients/Requests/UpdateClientRequestContent.cs +++ b/src/Auth0.ManagementApi/Clients/Requests/UpdateClientRequestContent.cs @@ -297,10 +297,22 @@ public record UpdateClientRequestContent [JsonPropertyName("express_configuration")] public Optional ExpressConfiguration { get; set; } + [Nullable, Optional] + [JsonPropertyName("my_organization_configuration")] + public Optional MyOrganizationConfiguration { get; set; } + [Nullable, Optional] [JsonPropertyName("async_approval_notification_channels")] public Optional?> AsyncApprovalNotificationChannels { get; set; } + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// public override string ToString() { diff --git a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/DirectoryProvisioningClient.cs b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/DirectoryProvisioningClient.cs index 436490796..d91040d27 100644 --- a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/DirectoryProvisioningClient.cs +++ b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/DirectoryProvisioningClient.cs @@ -497,6 +497,120 @@ private async Task< } } + /// + /// Retrieve the configured synchronized groups for a connection directory provisioning configuration. + /// + private WithRawResponseTask ListSynchronizedGroupsInternalAsync( + string id, + ListSynchronizedGroupsRequestParameters request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ) + { + return new WithRawResponseTask( + ListSynchronizedGroupsInternalAsyncCore(id, request, options, cancellationToken) + ); + } + + private async Task< + WithRawResponse + > ListSynchronizedGroupsInternalAsyncCore( + string id, + ListSynchronizedGroupsRequestParameters request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ) + { + var _queryString = new Auth0.ManagementApi.Core.QueryStringBuilder.Builder(capacity: 2) + .Add("from", request.From.IsDefined ? request.From.Value : null) + .Add("take", request.Take.IsDefined ? request.Take.Value : null) + .MergeAdditional(options?.AdditionalQueryParameters) + .Build(); + var _headers = await new Auth0.ManagementApi.Core.HeadersBuilder.Builder() + .Add(_client.Options.Headers) + .Add(_client.Options.AdditionalHeaders) + .Add(options?.AdditionalHeaders) + .BuildAsync() + .ConfigureAwait(false); + var response = await _client + .SendRequestAsync( + new JsonRequest + { + Method = HttpMethod.Get, + Path = string.Format( + "connections/{0}/directory-provisioning/synchronized-groups", + ValueConvert.ToPathParameterString(id) + ), + QueryString = _queryString, + Headers = _headers, + Options = options, + }, + cancellationToken + ) + .ConfigureAwait(false); + if (response.StatusCode is >= 200 and < 400) + { + var responseBody = await response + .Raw.Content.ReadAsStringAsync(cancellationToken) + .ConfigureAwait(false); + try + { + var responseData = JsonUtils.Deserialize( + responseBody + )!; + return new WithRawResponse() + { + Data = responseData, + RawResponse = new RawResponse() + { + StatusCode = response.Raw.StatusCode, + Url = response.Raw.RequestMessage?.RequestUri ?? new Uri("about:blank"), + Headers = ResponseHeaders.FromHttpResponseMessage(response.Raw), + }, + }; + } + catch (JsonException e) + { + throw new ManagementApiException( + "Failed to deserialize response", + response.StatusCode, + null, + e + ); + } + } + { + var responseBody = await response + .Raw.Content.ReadAsStringAsync(cancellationToken) + .ConfigureAwait(false); + try + { + switch (response.StatusCode) + { + case 400: + throw new BadRequestError(JsonUtils.Deserialize(responseBody)); + case 401: + throw new UnauthorizedError(JsonUtils.Deserialize(responseBody)); + case 403: + throw new ForbiddenError(JsonUtils.Deserialize(responseBody)); + case 404: + throw new NotFoundError(JsonUtils.Deserialize(responseBody)); + case 429: + throw new TooManyRequestsError(JsonUtils.Deserialize(responseBody)); + } + } + catch (JsonException) + { + // unable to map error response, throwing generic error + } + throw new ManagementApiException( + $"Error with status code {response.StatusCode}", + response.StatusCode, + responseBody + ); + } + } + /// /// Retrieve a list of directory provisioning configurations of a tenant. /// @@ -683,4 +797,137 @@ public WithRawResponseTask + /// Retrieve the configured synchronized groups for a connection directory provisioning configuration. + /// + /// + /// await client.Connections.DirectoryProvisioning.ListSynchronizedGroupsAsync( + /// "id", + /// new ListSynchronizedGroupsRequestParameters { From = "from", Take = 1 } + /// ); + /// + public async Task> ListSynchronizedGroupsAsync( + string id, + ListSynchronizedGroupsRequestParameters request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ) + { + if (request is not null) + { + request = request with { }; + } + var pager = await CursorPager< + ListSynchronizedGroupsRequestParameters, + RequestOptions?, + ListSynchronizedGroupsResponseContent, + string?, + SynchronizedGroupPayload + > + .CreateInstanceAsync( + request, + options, + async (request, options, cancellationToken) => + await ListSynchronizedGroupsInternalAsync( + id, + request, + options, + cancellationToken + ) + .WithRawResponse(), + (request, cursor) => + { + request.From = cursor; + }, + response => response.Next, + response => response.Groups?.ToList(), + cancellationToken + ) + .ConfigureAwait(false); + return pager; + } + + /// + /// Create or replace the selected groups for a connection directory provisioning configuration. + /// + /// + /// await client.Connections.DirectoryProvisioning.SetAsync( + /// "id", + /// new ReplaceSynchronizedGroupsRequestContent + /// { + /// Groups = new List<SynchronizedGroupPayload>() + /// { + /// new SynchronizedGroupPayload { Id = "id" }, + /// }, + /// } + /// ); + /// + public async Task SetAsync( + string id, + ReplaceSynchronizedGroupsRequestContent request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ) + { + var _headers = await new Auth0.ManagementApi.Core.HeadersBuilder.Builder() + .Add(_client.Options.Headers) + .Add(_client.Options.AdditionalHeaders) + .Add(options?.AdditionalHeaders) + .BuildAsync() + .ConfigureAwait(false); + var response = await _client + .SendRequestAsync( + new JsonRequest + { + Method = HttpMethod.Put, + Path = string.Format( + "connections/{0}/directory-provisioning/synchronized-groups", + ValueConvert.ToPathParameterString(id) + ), + Body = request, + Headers = _headers, + ContentType = "application/json", + Options = options, + }, + cancellationToken + ) + .ConfigureAwait(false); + if (response.StatusCode is >= 200 and < 400) + { + return; + } + { + var responseBody = await response + .Raw.Content.ReadAsStringAsync(cancellationToken) + .ConfigureAwait(false); + try + { + switch (response.StatusCode) + { + case 400: + throw new BadRequestError(JsonUtils.Deserialize(responseBody)); + case 401: + throw new UnauthorizedError(JsonUtils.Deserialize(responseBody)); + case 403: + throw new ForbiddenError(JsonUtils.Deserialize(responseBody)); + case 404: + throw new NotFoundError(JsonUtils.Deserialize(responseBody)); + case 409: + throw new ConflictError(JsonUtils.Deserialize(responseBody)); + case 429: + throw new TooManyRequestsError(JsonUtils.Deserialize(responseBody)); + } + } + catch (JsonException) + { + // unable to map error response, throwing generic error + } + throw new ManagementApiException( + $"Error with status code {response.StatusCode}", + response.StatusCode, + responseBody + ); + } + } } diff --git a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/IDirectoryProvisioningClient.cs b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/IDirectoryProvisioningClient.cs index 886026ca8..8f4920c3b 100644 --- a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/IDirectoryProvisioningClient.cs +++ b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/IDirectoryProvisioningClient.cs @@ -63,4 +63,24 @@ WithRawResponseTask GetDe RequestOptions? options = null, CancellationToken cancellationToken = default ); + + /// + /// Retrieve the configured synchronized groups for a connection directory provisioning configuration. + /// + Task> ListSynchronizedGroupsAsync( + string id, + ListSynchronizedGroupsRequestParameters request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ); + + /// + /// Create or replace the selected groups for a connection directory provisioning configuration. + /// + Task SetAsync( + string id, + ReplaceSynchronizedGroupsRequestContent request, + RequestOptions? options = null, + CancellationToken cancellationToken = default + ); } diff --git a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ListSynchronizedGroupsRequestParameters.cs b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ListSynchronizedGroupsRequestParameters.cs new file mode 100644 index 000000000..823834e2c --- /dev/null +++ b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ListSynchronizedGroupsRequestParameters.cs @@ -0,0 +1,26 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi.Connections; + +[Serializable] +public record ListSynchronizedGroupsRequestParameters +{ + /// + /// Optional Id from which to start selection. + /// + [JsonIgnore] + public Optional From { get; set; } + + /// + /// Number of results per page. Defaults to 50. + /// + [JsonIgnore] + public Optional Take { get; set; } = 50; + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ReplaceSynchronizedGroupsRequestContent.cs b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ReplaceSynchronizedGroupsRequestContent.cs new file mode 100644 index 000000000..b888251ff --- /dev/null +++ b/src/Auth0.ManagementApi/Connections/DirectoryProvisioning/Requests/ReplaceSynchronizedGroupsRequestContent.cs @@ -0,0 +1,22 @@ +using Auth0.ManagementApi; +using Auth0.ManagementApi.Core; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi.Connections; + +[Serializable] +public record ReplaceSynchronizedGroupsRequestContent +{ + /// + /// Array of Google Workspace Directory group objects to synchronize. + /// + [JsonPropertyName("groups")] + public IEnumerable Groups { get; set; } = + new List(); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Core/CustomDomainInterceptor.cs b/src/Auth0.ManagementApi/Core/CustomDomainInterceptor.cs new file mode 100644 index 000000000..2a6125fbc --- /dev/null +++ b/src/Auth0.ManagementApi/Core/CustomDomainInterceptor.cs @@ -0,0 +1,88 @@ +using System.Text.RegularExpressions; + +namespace Auth0.ManagementApi.Core; + +/// +/// A that enforces the Auth0-Custom-Domain header whitelist. +/// +/// +/// The Auth0-Custom-Domain header is only meaningful for specific Management API endpoints +/// that generate user-facing links (email verification, password reset, invitations, etc.). +/// This handler strips the header from requests to any path not on the whitelist, preventing +/// it from leaking to unrelated endpoints. +/// +/// +/// Whitelisted paths: +/// +/// POST /tickets/email-verification +/// POST /tickets/password-change +/// POST /organizations/{id}/invitations +/// POST /guardian/enrollments/ticket +/// POST /jobs/verification-email +/// POST /jobs/users-imports +/// POST /users and PATCH /users/{id} +/// POST /self-service-profiles/{id}/sso-ticket +/// +/// +public class CustomDomainInterceptor : DelegatingHandler +{ + /// + /// The name of the custom domain header. + /// + public const string HeaderName = "Auth0-Custom-Domain"; + + private static readonly Regex[] WhitelistedPaths = + { + new Regex(@".*/tickets/email-verification$", RegexOptions.Compiled), + new Regex(@".*/tickets/password-change$", RegexOptions.Compiled), + new Regex(@".*/organizations/[^/]+/invitations(/[^/]+)?$", RegexOptions.Compiled), + new Regex(@".*/guardian/enrollments/ticket$", RegexOptions.Compiled), + new Regex(@".*/jobs/verification-email$", RegexOptions.Compiled), + new Regex(@".*/jobs/users-imports$", RegexOptions.Compiled), + new Regex(@".*/users(/[^/]+)?$", RegexOptions.Compiled), + new Regex(@".*/self-service-profiles/[^/]+/sso-ticket(/[^/]+/revoke)?$", RegexOptions.Compiled), + }; + + /// + /// Initializes a new instance of with a default + /// as the inner handler. + /// + public CustomDomainInterceptor() + : base(new HttpClientHandler()) { } + + /// + /// Initializes a new instance of wrapping the + /// specified inner handler. + /// + /// The inner to delegate to. + /// Thrown when is null. + public CustomDomainInterceptor(HttpMessageHandler innerHandler) + : base(innerHandler ?? throw new ArgumentNullException(nameof(innerHandler))) { } + + /// + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (request.Headers.Contains(HeaderName) && + !IsWhitelisted(request.RequestUri?.AbsolutePath)) + { + request.Headers.Remove(HeaderName); + } + + return base.SendAsync(request, cancellationToken); + } + + /// + /// Returns true if matches one of the whitelisted endpoint patterns. + /// Used internally by and exposed for unit testing via InternalsVisibleTo. + /// + /// The URL absolute path to test (e.g. /api/v2/tickets/email-verification). + internal static bool IsWhitelisted(string? path) + { + if (string.IsNullOrEmpty(path)) + return false; + + return WhitelistedPaths.Any(p => p.IsMatch(path)); + } +} diff --git a/src/Auth0.ManagementApi/Core/Public/ClientOptions.Custom.cs b/src/Auth0.ManagementApi/Core/Public/ClientOptions.Custom.cs index 725d7e464..7398bfeb7 100644 --- a/src/Auth0.ManagementApi/Core/Public/ClientOptions.Custom.cs +++ b/src/Auth0.ManagementApi/Core/Public/ClientOptions.Custom.cs @@ -1,10 +1,59 @@ using System.Text; using System.Text.Json; +using Auth0.ManagementApi.Core; namespace Auth0.ManagementApi; public partial class ClientOptions { + private string? _customDomain; + + /// + /// Sets the Auth0-Custom-Domain header value sent on Management API requests that + /// generate user-facing links (email verification, password reset, invitations, etc.). + /// + /// + /// When set, the header is included in every outgoing request. To restrict the + /// header to only the whitelisted endpoints and strip it from all others, also configure + /// your with a handler: + /// + /// new ClientOptions + /// { + /// CustomDomain = "login.mycompany.com", + /// HttpClient = new HttpClient(new CustomDomainInterceptor()) + /// } + /// + /// + /// + /// + /// If you are using , stripping is configured automatically + /// when no custom is provided - prefer that path. + /// + /// + /// Thrown when the value is non-null but empty or contains only whitespace. + public string? CustomDomain + { + get => _customDomain; +#if NET5_0_OR_GREATER + init +#else + set +#endif + { + if (!string.IsNullOrWhiteSpace(value)) + { + _customDomain = value; + Headers[CustomDomainInterceptor.HeaderName] = value; + } + else if (value != null) + { + throw new ArgumentException( + "CustomDomain must not be empty or contain only whitespace.", + nameof(value)); + } + } + } + public ClientOptions() { Headers["Auth0-Client"] = CreateAgentString(); diff --git a/src/Auth0.ManagementApi/CustomDomainHeader.cs b/src/Auth0.ManagementApi/CustomDomainHeader.cs new file mode 100644 index 000000000..47363f209 --- /dev/null +++ b/src/Auth0.ManagementApi/CustomDomainHeader.cs @@ -0,0 +1,65 @@ +using Auth0.ManagementApi.Core; + +namespace Auth0.ManagementApi; + +/// +/// Convenience helper for creating per-request Auth0-Custom-Domain overrides. +/// +/// +/// Use this when you need to specify a custom domain for a single API call without +/// configuring it globally on the client. The header is forwarded only to whitelisted +/// endpoints — if you have a configured on your +/// , it is stripped automatically from any +/// non-whitelisted path. +/// +/// +/// +/// When you need the custom domain header and other +/// settings (extra headers, timeout, retries) in the same call, construct +/// directly instead of using this helper: +/// +/// await client.Tickets.VerifyEmailAsync(request, new RequestOptions +/// { +/// AdditionalHeaders = new[] +/// { +/// new KeyValuePair<string, string?>(CustomDomainInterceptor.HeaderName, "login.mycompany.com"), +/// new KeyValuePair<string, string?>("X-Correlation-Id", "abc-123"), +/// }, +/// MaxRetries = 1, +/// }); +/// +/// +/// +/// +/// +/// // Override for a specific request +/// await client.Tickets.VerifyEmailAsync(request, CustomDomainHeader.For("login.mycompany.com")); +/// +/// // Override for organization invitations +/// await client.Organizations.Invitations.CreateAsync(orgId, invitation, CustomDomainHeader.For("login.mycompany.com")); +/// +/// +/// +public static class CustomDomainHeader +{ + /// + /// Creates a with the Auth0-Custom-Domain header set + /// to . + /// + /// The custom domain (e.g. "login.mycompany.com"). + /// A carrying the custom domain header. + /// Thrown when is null, empty, or whitespace. + public static RequestOptions For(string domain) + { + if (string.IsNullOrWhiteSpace(domain)) + throw new ArgumentException("Domain must not be null or whitespace.", nameof(domain)); + + return new RequestOptions + { + AdditionalHeaders = new[] + { + new KeyValuePair(CustomDomainInterceptor.HeaderName, domain), + }, + }; + } +} diff --git a/src/Auth0.ManagementApi/EventStreams/EventStreamsClient.cs b/src/Auth0.ManagementApi/EventStreams/EventStreamsClient.cs index 4e6ab1beb..609aed5e3 100644 --- a/src/Auth0.ManagementApi/EventStreams/EventStreamsClient.cs +++ b/src/Auth0.ManagementApi/EventStreams/EventStreamsClient.cs @@ -646,7 +646,7 @@ public WithRawResponseTask UpdateAsync( /// "id", /// new CreateEventStreamTestEventRequestContent /// { - /// EventType = EventStreamTestEventTypeEnum.UserCreated, + /// EventType = EventStreamTestEventTypeEnum.GroupCreated, /// } /// ); /// diff --git a/src/Auth0.ManagementApi/LogStreams/ILogStreamsClient.cs b/src/Auth0.ManagementApi/LogStreams/ILogStreamsClient.cs index a742d1cbb..b55e2b0e5 100644 --- a/src/Auth0.ManagementApi/LogStreams/ILogStreamsClient.cs +++ b/src/Auth0.ManagementApi/LogStreams/ILogStreamsClient.cs @@ -3,72 +3,77 @@ namespace Auth0.ManagementApi; public partial interface ILogStreamsClient { /// - /// Retrieve details on log streams. - /// Sample Response[{ - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active|paused|suspended", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } + /// Retrieve details on [log streams](https://auth0.com/docs/logs/streams). + /// + /// **Sample Response** + /// + /// ```json + /// [{ + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active|paused|suspended", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } /// }, { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active|paused|suspended", - /// "sink": { - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpContentType": "string", - /// "httpEndpoint": "string", - /// "httpAuthorization": "string" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active|paused|suspended", + /// "sink": { + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpContentType": "string", + /// "httpEndpoint": "string", + /// "httpAuthorization": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "eventgrid", - /// "status": "active|paused|suspended", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string", - /// "azurePartnerTopic": "string" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "eventgrid", + /// "status": "active|paused|suspended", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string", + /// "azurePartnerTopic": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active|paused|suspended", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active|paused|suspended", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active|paused|suspended", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active|paused|suspended", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active|paused|suspended", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// }] + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active|paused|suspended", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// }] + /// ``` /// WithRawResponseTask> ListAsync( RequestOptions? options = null, @@ -77,131 +82,202 @@ WithRawResponseTask> ListAsync( /// /// Create a log stream. - /// Log Stream Types The type of log stream being created determines the properties required in the sink payload. - /// HTTP Stream For an http Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "http", - /// "sink": { - /// "httpEndpoint": "string", - /// "httpContentType": "string", - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpAuthorization": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active", - /// "sink": { - /// "httpEndpoint": "string", - /// "httpContentType": "string", - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpAuthorization": "string" - /// } - /// } - /// Amazon EventBridge Stream For an eventbridge Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "eventbridge", - /// "sink": { - /// "awsRegion": "string", - /// "awsAccountId": "string" - /// } - /// } - /// The response will include an additional field awsPartnerEventSource in the sink: { - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } - /// } - /// Azure Event Grid Stream For an Azure Event Grid Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "eventgrid", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string", - /// "azurePartnerTopic": "string" - /// } - /// } - /// Datadog Stream For a Datadog Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "datadog", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// } - /// Splunk Stream For a Splunk Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "splunk", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } - /// Sumo Logic Stream For a Sumo Logic Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "sumo", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } + /// + /// **Log Stream Types** + /// + /// The `type` of log stream being created determines the properties required in the `sink` payload. + /// + /// **HTTP Stream** + /// + /// For an `http` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "http", + /// "sink": { + /// "httpEndpoint": "string", + /// "httpContentType": "string", + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active", + /// "sink": { + /// "httpEndpoint": "string", + /// "httpContentType": "string", + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Amazon EventBridge Stream** + /// + /// For an `eventbridge` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "eventbridge", + /// "sink": { + /// "awsRegion": "string", + /// "awsAccountId": "string" + /// } + /// } + /// ``` + /// + /// The response will include an additional field `awsPartnerEventSource` in the `sink`: + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } + /// } + /// ``` + /// + /// **Azure Event Grid Stream** + /// + /// For an `Azure Event Grid` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "eventgrid", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string", + /// "azurePartnerTopic": "string" + /// } + /// } + /// ``` + /// + /// **Datadog Stream** + /// + /// For a `Datadog` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "datadog", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Splunk Stream** + /// + /// For a `Splunk` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "splunk", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Sumo Logic Stream** + /// + /// For a `Sumo Logic` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "sumo", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` /// WithRawResponseTask CreateAsync( CreateLogStreamRequestContent request, @@ -211,107 +287,157 @@ WithRawResponseTask CreateAsync( /// /// Retrieve a log stream configuration and status. - /// Sample responsesAmazon EventBridge Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active|paused|suspended", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } - /// } HTTP Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active|paused|suspended", - /// "sink": { - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpContentType": "string", - /// "httpEndpoint": "string", - /// "httpAuthorization": "string" - /// } - /// } Datadog Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active|paused|suspended", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// - /// }Mixpanel - /// - /// Request: { - /// "name": "string", - /// "type": "mixpanel", - /// "sink": { - /// "mixpanelRegion": "string", // "us" | "eu", - /// "mixpanelProjectId": "string", - /// "mixpanelServiceAccountUsername": "string", - /// "mixpanelServiceAccountPassword": "string" - /// } - /// } - /// - /// - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "mixpanel", - /// "status": "active", - /// "sink": { - /// "mixpanelRegion": "string", // "us" | "eu", - /// "mixpanelProjectId": "string", - /// "mixpanelServiceAccountUsername": "string", - /// "mixpanelServiceAccountPassword": "string" // the following is redacted on return - /// } - /// } - /// - /// Segment - /// - /// Request: { - /// "name": "string", - /// "type": "segment", - /// "sink": { - /// "segmentWriteKey": "string" - /// } - /// } - /// - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "segment", - /// "status": "active", - /// "sink": { - /// "segmentWriteKey": "string" - /// } - /// } - /// - /// Splunk Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active|paused|suspended", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } Sumo Logic Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active|paused|suspended", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } Status The status of a log stream maybe any of the following: - /// 1. active - Stream is currently enabled. - /// 2. paused - Stream is currently user disabled and will not attempt log delivery. - /// 3. suspended - Stream is currently disabled because of errors and will not attempt log delivery. + /// + /// **Sample responses** + /// + /// **Amazon EventBridge Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active|paused|suspended", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } + /// } + /// ``` + /// + /// **HTTP Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active|paused|suspended", + /// "sink": { + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpContentType": "string", + /// "httpEndpoint": "string", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Datadog Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active|paused|suspended", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Mixpanel** + /// + /// **Request:** + /// + /// ```json + /// { + /// "name": "string", + /// "type": "mixpanel", + /// "sink": { + /// "mixpanelRegion": "string", + /// "mixpanelProjectId": "string", + /// "mixpanelServiceAccountUsername": "string", + /// "mixpanelServiceAccountPassword": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "mixpanel", + /// "status": "active", + /// "sink": { + /// "mixpanelRegion": "string", + /// "mixpanelProjectId": "string", + /// "mixpanelServiceAccountUsername": "string", + /// "mixpanelServiceAccountPassword": "string" + /// } + /// } + /// ``` + /// + /// **Segment** + /// + /// **Request:** + /// + /// ```json + /// { + /// "name": "string", + /// "type": "segment", + /// "sink": { + /// "segmentWriteKey": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "segment", + /// "status": "active", + /// "sink": { + /// "segmentWriteKey": "string" + /// } + /// } + /// ``` + /// + /// **Splunk Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active|paused|suspended", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Sumo Logic Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active|paused|suspended", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` + /// + /// **Status** + /// + /// The `status` of a log stream maybe any of the following: + /// + /// 1. `active` - Stream is currently enabled. + /// 2. `paused` - Stream is currently user disabled and will not attempt log delivery. + /// 3. `suspended` - Stream is currently disabled because of errors and will not attempt log delivery. /// WithRawResponseTask GetAsync( string id, @@ -330,40 +456,79 @@ Task DeleteAsync( /// /// Update a log stream. - /// Examples of how to use the PATCH endpoint. The following fields may be updated in a PATCH operation: namestatussink Note: For log streams of type eventbridge and eventgrid, updating the sink is not permitted. - /// Update the status of a log stream{ - /// "status": "active|paused" - /// } - /// Update the name of a log stream{ - /// "name": "string" - /// } - /// Update the sink properties of a stream of type http{ + /// + /// **Examples of how to use the PATCH endpoint.** + /// + /// The following fields may be updated in a PATCH operation: + /// + /// - name + /// - status + /// - sink + /// + /// Note: For log streams of type `eventbridge` and `eventgrid`, updating the `sink` is not permitted. + /// + /// **Update the status of a log stream** + /// + /// ```json + /// { + /// "status": "active|paused" + /// } + /// ``` + /// + /// **Update the name of a log stream** + /// + /// ```json + /// { + /// "name": "string" + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `http`** + /// + /// ```json + /// { /// "sink": { /// "httpEndpoint": "string", /// "httpContentType": "string", /// "httpContentFormat": "JSONARRAY|JSONLINES", /// "httpAuthorization": "string" /// } - /// } - /// Update the sink properties of a stream of type datadog{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `datadog`** + /// + /// ```json + /// { /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" + /// "datadogRegion": "string", + /// "datadogApiKey": "string" /// } - /// } - /// Update the sink properties of a stream of type splunk{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `splunk`** + /// + /// ```json + /// { /// "sink": { /// "splunkDomain": "string", /// "splunkToken": "string", /// "splunkPort": "string", /// "splunkSecure": "boolean" /// } - /// } - /// Update the sink properties of a stream of type sumo{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `sumo`** + /// + /// ```json + /// { /// "sink": { /// "sumoSourceAddress": "string" /// } - /// } + /// } + /// ``` /// WithRawResponseTask UpdateAsync( string id, diff --git a/src/Auth0.ManagementApi/LogStreams/LogStreamsClient.cs b/src/Auth0.ManagementApi/LogStreams/LogStreamsClient.cs index 38c61d298..fddfaf6af 100644 --- a/src/Auth0.ManagementApi/LogStreams/LogStreamsClient.cs +++ b/src/Auth0.ManagementApi/LogStreams/LogStreamsClient.cs @@ -359,72 +359,77 @@ private async Task> UpdateAsyncC } /// - /// Retrieve details on log streams. - /// Sample Response[{ - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active|paused|suspended", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } + /// Retrieve details on [log streams](https://auth0.com/docs/logs/streams). + /// + /// **Sample Response** + /// + /// ```json + /// [{ + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active|paused|suspended", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } /// }, { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active|paused|suspended", - /// "sink": { - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpContentType": "string", - /// "httpEndpoint": "string", - /// "httpAuthorization": "string" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active|paused|suspended", + /// "sink": { + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpContentType": "string", + /// "httpEndpoint": "string", + /// "httpAuthorization": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "eventgrid", - /// "status": "active|paused|suspended", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string", - /// "azurePartnerTopic": "string" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "eventgrid", + /// "status": "active|paused|suspended", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string", + /// "azurePartnerTopic": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active|paused|suspended", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active|paused|suspended", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active|paused|suspended", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active|paused|suspended", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } /// }, /// { - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active|paused|suspended", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// }] + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active|paused|suspended", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// }] + /// ``` /// /// /// await client.LogStreams.ListAsync(); @@ -441,131 +446,202 @@ public WithRawResponseTask> ListAsync( /// /// Create a log stream. - /// Log Stream Types The type of log stream being created determines the properties required in the sink payload. - /// HTTP Stream For an http Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "http", - /// "sink": { - /// "httpEndpoint": "string", - /// "httpContentType": "string", - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpAuthorization": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active", - /// "sink": { - /// "httpEndpoint": "string", - /// "httpContentType": "string", - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpAuthorization": "string" - /// } - /// } - /// Amazon EventBridge Stream For an eventbridge Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "eventbridge", - /// "sink": { - /// "awsRegion": "string", - /// "awsAccountId": "string" - /// } - /// } - /// The response will include an additional field awsPartnerEventSource in the sink: { - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } - /// } - /// Azure Event Grid Stream For an Azure Event Grid Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "eventgrid", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active", - /// "sink": { - /// "azureSubscriptionId": "string", - /// "azureResourceGroup": "string", - /// "azureRegion": "string", - /// "azurePartnerTopic": "string" - /// } - /// } - /// Datadog Stream For a Datadog Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "datadog", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// } - /// Splunk Stream For a Splunk Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "splunk", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } - /// Sumo Logic Stream For a Sumo Logic Stream, the sink properties are listed in the payload below - /// Request: { - /// "name": "string", - /// "type": "sumo", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } + /// + /// **Log Stream Types** + /// + /// The `type` of log stream being created determines the properties required in the `sink` payload. + /// + /// **HTTP Stream** + /// + /// For an `http` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "http", + /// "sink": { + /// "httpEndpoint": "string", + /// "httpContentType": "string", + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active", + /// "sink": { + /// "httpEndpoint": "string", + /// "httpContentType": "string", + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Amazon EventBridge Stream** + /// + /// For an `eventbridge` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "eventbridge", + /// "sink": { + /// "awsRegion": "string", + /// "awsAccountId": "string" + /// } + /// } + /// ``` + /// + /// The response will include an additional field `awsPartnerEventSource` in the `sink`: + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } + /// } + /// ``` + /// + /// **Azure Event Grid Stream** + /// + /// For an `Azure Event Grid` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "eventgrid", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active", + /// "sink": { + /// "azureSubscriptionId": "string", + /// "azureResourceGroup": "string", + /// "azureRegion": "string", + /// "azurePartnerTopic": "string" + /// } + /// } + /// ``` + /// + /// **Datadog Stream** + /// + /// For a `Datadog` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "datadog", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Splunk Stream** + /// + /// For a `Splunk` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "splunk", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Sumo Logic Stream** + /// + /// For a `Sumo Logic` Stream, the `sink` properties are listed in the payload below. + /// + /// **Request:** + /// ```json + /// { + /// "name": "string", + /// "type": "sumo", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` /// /// /// await client.LogStreams.CreateAsync( @@ -589,107 +665,157 @@ public WithRawResponseTask CreateAsync( /// /// Retrieve a log stream configuration and status. - /// Sample responsesAmazon EventBridge Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "eventbridge", - /// "status": "active|paused|suspended", - /// "sink": { - /// "awsAccountId": "string", - /// "awsRegion": "string", - /// "awsPartnerEventSource": "string" - /// } - /// } HTTP Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "http", - /// "status": "active|paused|suspended", - /// "sink": { - /// "httpContentFormat": "JSONLINES|JSONARRAY", - /// "httpContentType": "string", - /// "httpEndpoint": "string", - /// "httpAuthorization": "string" - /// } - /// } Datadog Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "datadog", - /// "status": "active|paused|suspended", - /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" - /// } - /// - /// }Mixpanel - /// - /// Request: { - /// "name": "string", - /// "type": "mixpanel", - /// "sink": { - /// "mixpanelRegion": "string", // "us" | "eu", - /// "mixpanelProjectId": "string", - /// "mixpanelServiceAccountUsername": "string", - /// "mixpanelServiceAccountPassword": "string" - /// } - /// } - /// - /// - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "mixpanel", - /// "status": "active", - /// "sink": { - /// "mixpanelRegion": "string", // "us" | "eu", - /// "mixpanelProjectId": "string", - /// "mixpanelServiceAccountUsername": "string", - /// "mixpanelServiceAccountPassword": "string" // the following is redacted on return - /// } - /// } - /// - /// Segment - /// - /// Request: { - /// "name": "string", - /// "type": "segment", - /// "sink": { - /// "segmentWriteKey": "string" - /// } - /// } - /// - /// Response: { - /// "id": "string", - /// "name": "string", - /// "type": "segment", - /// "status": "active", - /// "sink": { - /// "segmentWriteKey": "string" - /// } - /// } - /// - /// Splunk Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "splunk", - /// "status": "active|paused|suspended", - /// "sink": { - /// "splunkDomain": "string", - /// "splunkToken": "string", - /// "splunkPort": "string", - /// "splunkSecure": "boolean" - /// } - /// } Sumo Logic Log Stream{ - /// "id": "string", - /// "name": "string", - /// "type": "sumo", - /// "status": "active|paused|suspended", - /// "sink": { - /// "sumoSourceAddress": "string", - /// } - /// } Status The status of a log stream maybe any of the following: - /// 1. active - Stream is currently enabled. - /// 2. paused - Stream is currently user disabled and will not attempt log delivery. - /// 3. suspended - Stream is currently disabled because of errors and will not attempt log delivery. + /// + /// **Sample responses** + /// + /// **Amazon EventBridge Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "eventbridge", + /// "status": "active|paused|suspended", + /// "sink": { + /// "awsAccountId": "string", + /// "awsRegion": "string", + /// "awsPartnerEventSource": "string" + /// } + /// } + /// ``` + /// + /// **HTTP Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "http", + /// "status": "active|paused|suspended", + /// "sink": { + /// "httpContentFormat": "JSONLINES|JSONARRAY", + /// "httpContentType": "string", + /// "httpEndpoint": "string", + /// "httpAuthorization": "string" + /// } + /// } + /// ``` + /// + /// **Datadog Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "datadog", + /// "status": "active|paused|suspended", + /// "sink": { + /// "datadogRegion": "string", + /// "datadogApiKey": "string" + /// } + /// } + /// ``` + /// + /// **Mixpanel** + /// + /// **Request:** + /// + /// ```json + /// { + /// "name": "string", + /// "type": "mixpanel", + /// "sink": { + /// "mixpanelRegion": "string", + /// "mixpanelProjectId": "string", + /// "mixpanelServiceAccountUsername": "string", + /// "mixpanelServiceAccountPassword": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "mixpanel", + /// "status": "active", + /// "sink": { + /// "mixpanelRegion": "string", + /// "mixpanelProjectId": "string", + /// "mixpanelServiceAccountUsername": "string", + /// "mixpanelServiceAccountPassword": "string" + /// } + /// } + /// ``` + /// + /// **Segment** + /// + /// **Request:** + /// + /// ```json + /// { + /// "name": "string", + /// "type": "segment", + /// "sink": { + /// "segmentWriteKey": "string" + /// } + /// } + /// ``` + /// + /// **Response:** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "segment", + /// "status": "active", + /// "sink": { + /// "segmentWriteKey": "string" + /// } + /// } + /// ``` + /// + /// **Splunk Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "splunk", + /// "status": "active|paused|suspended", + /// "sink": { + /// "splunkDomain": "string", + /// "splunkToken": "string", + /// "splunkPort": "string", + /// "splunkSecure": "boolean" + /// } + /// } + /// ``` + /// + /// **Sumo Logic Log Stream** + /// + /// ```json + /// { + /// "id": "string", + /// "name": "string", + /// "type": "sumo", + /// "status": "active|paused|suspended", + /// "sink": { + /// "sumoSourceAddress": "string" + /// } + /// } + /// ``` + /// + /// **Status** + /// + /// The `status` of a log stream maybe any of the following: + /// + /// 1. `active` - Stream is currently enabled. + /// 2. `paused` - Stream is currently user disabled and will not attempt log delivery. + /// 3. `suspended` - Stream is currently disabled because of errors and will not attempt log delivery. /// /// /// await client.LogStreams.GetAsync("id"); @@ -773,40 +899,79 @@ public async Task DeleteAsync( /// /// Update a log stream. - /// Examples of how to use the PATCH endpoint. The following fields may be updated in a PATCH operation: namestatussink Note: For log streams of type eventbridge and eventgrid, updating the sink is not permitted. - /// Update the status of a log stream{ - /// "status": "active|paused" - /// } - /// Update the name of a log stream{ - /// "name": "string" - /// } - /// Update the sink properties of a stream of type http{ + /// + /// **Examples of how to use the PATCH endpoint.** + /// + /// The following fields may be updated in a PATCH operation: + /// + /// - name + /// - status + /// - sink + /// + /// Note: For log streams of type `eventbridge` and `eventgrid`, updating the `sink` is not permitted. + /// + /// **Update the status of a log stream** + /// + /// ```json + /// { + /// "status": "active|paused" + /// } + /// ``` + /// + /// **Update the name of a log stream** + /// + /// ```json + /// { + /// "name": "string" + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `http`** + /// + /// ```json + /// { /// "sink": { /// "httpEndpoint": "string", /// "httpContentType": "string", /// "httpContentFormat": "JSONARRAY|JSONLINES", /// "httpAuthorization": "string" /// } - /// } - /// Update the sink properties of a stream of type datadog{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `datadog`** + /// + /// ```json + /// { /// "sink": { - /// "datadogRegion": "string", - /// "datadogApiKey": "string" + /// "datadogRegion": "string", + /// "datadogApiKey": "string" /// } - /// } - /// Update the sink properties of a stream of type splunk{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `splunk`** + /// + /// ```json + /// { /// "sink": { /// "splunkDomain": "string", /// "splunkToken": "string", /// "splunkPort": "string", /// "splunkSecure": "boolean" /// } - /// } - /// Update the sink properties of a stream of type sumo{ + /// } + /// ``` + /// + /// **Update the sink properties of a stream of type `sumo`** + /// + /// ```json + /// { /// "sink": { /// "sumoSourceAddress": "string" /// } - /// } + /// } + /// ``` /// /// /// await client.LogStreams.UpdateAsync("id", new UpdateLogStreamRequestContent()); diff --git a/src/Auth0.ManagementApi/SelfServiceProfiles/SsoTicket/Requests/CreateSelfServiceProfileSsoTicketRequestContent.cs b/src/Auth0.ManagementApi/SelfServiceProfiles/SsoTicket/Requests/CreateSelfServiceProfileSsoTicketRequestContent.cs index 40798dbb3..4f294e823 100644 --- a/src/Auth0.ManagementApi/SelfServiceProfiles/SsoTicket/Requests/CreateSelfServiceProfileSsoTicketRequestContent.cs +++ b/src/Auth0.ManagementApi/SelfServiceProfiles/SsoTicket/Requests/CreateSelfServiceProfileSsoTicketRequestContent.cs @@ -54,6 +54,10 @@ public record CreateSelfServiceProfileSsoTicketRequestContent [JsonPropertyName("use_for_organization_discovery")] public bool? UseForOrganizationDiscovery { get; set; } + [Optional] + [JsonPropertyName("enabled_features")] + public SelfServiceProfileSsoTicketEnabledFeatures? EnabledFeatures { get; set; } + /// public override string ToString() { diff --git a/src/Auth0.ManagementApi/Tenants/Settings/Requests/UpdateTenantSettingsRequestContent.cs b/src/Auth0.ManagementApi/Tenants/Settings/Requests/UpdateTenantSettingsRequestContent.cs index 3a40216fb..12b063c74 100644 --- a/src/Auth0.ManagementApi/Tenants/Settings/Requests/UpdateTenantSettingsRequestContent.cs +++ b/src/Auth0.ManagementApi/Tenants/Settings/Requests/UpdateTenantSettingsRequestContent.cs @@ -203,6 +203,13 @@ public record UpdateTenantSettingsRequestContent [JsonPropertyName("resource_parameter_profile")] public TenantSettingsResourceParameterProfile? ResourceParameterProfile { get; set; } + /// + /// Whether the authorization server supports retrieving client metadata from a client_id URL. + /// + [Optional] + [JsonPropertyName("client_id_metadata_document_supported")] + public bool? ClientIdMetadataDocumentSupported { get; set; } + /// /// Whether Auth0 Guide (AI-powered assistance) is enabled for this tenant. /// @@ -217,6 +224,10 @@ public record UpdateTenantSettingsRequestContent [JsonPropertyName("phone_consolidated_experience")] public bool? PhoneConsolidatedExperience { get; set; } + [Optional] + [JsonPropertyName("dynamic_client_registration_security_mode")] + public TenantSettingsDynamicClientRegistrationSecurityMode? DynamicClientRegistrationSecurityMode { get; set; } + /// public override string ToString() { diff --git a/src/Auth0.ManagementApi/Types/Client.cs b/src/Auth0.ManagementApi/Types/Client.cs index 6be1d6574..6aa6d524e 100644 --- a/src/Auth0.ManagementApi/Types/Client.cs +++ b/src/Auth0.ManagementApi/Types/Client.cs @@ -309,6 +309,18 @@ public record Client : IJsonOnDeserialized, IJsonOnSerializing [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationResponseConfiguration? MyOrganizationConfiguration { get; set; } + + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// /// The identifier of the resource server that this client is linked to. /// diff --git a/src/Auth0.ManagementApi/Types/ClientGrantDefaultForEnum.cs b/src/Auth0.ManagementApi/Types/ClientGrantDefaultForEnum.cs new file mode 100644 index 000000000..f4a1833b4 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientGrantDefaultForEnum.cs @@ -0,0 +1,113 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter(typeof(ClientGrantDefaultForEnum.ClientGrantDefaultForEnumSerializer))] +[Serializable] +public readonly record struct ClientGrantDefaultForEnum : IStringEnum +{ + public static readonly ClientGrantDefaultForEnum ThirdPartyClients = new( + Values.ThirdPartyClients + ); + + public ClientGrantDefaultForEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientGrantDefaultForEnum FromCustom(string value) + { + return new ClientGrantDefaultForEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==(ClientGrantDefaultForEnum value1, string value2) => + value1.Value.Equals(value2); + + public static bool operator !=(ClientGrantDefaultForEnum value1, string value2) => + !value1.Value.Equals(value2); + + public static explicit operator string(ClientGrantDefaultForEnum value) => value.Value; + + public static explicit operator ClientGrantDefaultForEnum(string value) => new(value); + + internal class ClientGrantDefaultForEnumSerializer : JsonConverter + { + public override ClientGrantDefaultForEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientGrantDefaultForEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientGrantDefaultForEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientGrantDefaultForEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientGrantDefaultForEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientGrantDefaultForEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string ThirdPartyClients = "third_party_clients"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientGrantResponseContent.cs b/src/Auth0.ManagementApi/Types/ClientGrantResponseContent.cs index 942ce9eba..4046a23c1 100644 --- a/src/Auth0.ManagementApi/Types/ClientGrantResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/ClientGrantResponseContent.cs @@ -50,6 +50,10 @@ public record ClientGrantResponseContent : IJsonOnDeserialized [JsonPropertyName("allow_any_organization")] public bool? AllowAnyOrganization { get; set; } + [Optional] + [JsonPropertyName("default_for")] + public ClientGrantDefaultForEnum? DefaultFor { get; set; } + /// /// If enabled, this grant is a special grant created by Auth0. It cannot be modified or deleted directly. /// diff --git a/src/Auth0.ManagementApi/Types/ClientMyOrganizationConfigurationAllowedStrategiesEnum.cs b/src/Auth0.ManagementApi/Types/ClientMyOrganizationConfigurationAllowedStrategiesEnum.cs new file mode 100644 index 000000000..8b221d0ec --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientMyOrganizationConfigurationAllowedStrategiesEnum.cs @@ -0,0 +1,159 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter( + typeof(ClientMyOrganizationConfigurationAllowedStrategiesEnum.ClientMyOrganizationConfigurationAllowedStrategiesEnumSerializer) +)] +[Serializable] +public readonly record struct ClientMyOrganizationConfigurationAllowedStrategiesEnum : IStringEnum +{ + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Pingfederate = + new(Values.Pingfederate); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Adfs = new( + Values.Adfs + ); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Waad = new( + Values.Waad + ); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum GoogleApps = new( + Values.GoogleApps + ); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Okta = new( + Values.Okta + ); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Oidc = new( + Values.Oidc + ); + + public static readonly ClientMyOrganizationConfigurationAllowedStrategiesEnum Samlp = new( + Values.Samlp + ); + + public ClientMyOrganizationConfigurationAllowedStrategiesEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientMyOrganizationConfigurationAllowedStrategiesEnum FromCustom(string value) + { + return new ClientMyOrganizationConfigurationAllowedStrategiesEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==( + ClientMyOrganizationConfigurationAllowedStrategiesEnum value1, + string value2 + ) => value1.Value.Equals(value2); + + public static bool operator !=( + ClientMyOrganizationConfigurationAllowedStrategiesEnum value1, + string value2 + ) => !value1.Value.Equals(value2); + + public static explicit operator string( + ClientMyOrganizationConfigurationAllowedStrategiesEnum value + ) => value.Value; + + public static explicit operator ClientMyOrganizationConfigurationAllowedStrategiesEnum( + string value + ) => new(value); + + internal class ClientMyOrganizationConfigurationAllowedStrategiesEnumSerializer + : JsonConverter + { + public override ClientMyOrganizationConfigurationAllowedStrategiesEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientMyOrganizationConfigurationAllowedStrategiesEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientMyOrganizationConfigurationAllowedStrategiesEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientMyOrganizationConfigurationAllowedStrategiesEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientMyOrganizationConfigurationAllowedStrategiesEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientMyOrganizationConfigurationAllowedStrategiesEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Pingfederate = "pingfederate"; + + public const string Adfs = "adfs"; + + public const string Waad = "waad"; + + public const string GoogleApps = "google-apps"; + + public const string Okta = "okta"; + + public const string Oidc = "oidc"; + + public const string Samlp = "samlp"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientMyOrganizationDeletionBehaviorEnum.cs b/src/Auth0.ManagementApi/Types/ClientMyOrganizationDeletionBehaviorEnum.cs new file mode 100644 index 000000000..d0c3049a6 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientMyOrganizationDeletionBehaviorEnum.cs @@ -0,0 +1,126 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter( + typeof(ClientMyOrganizationDeletionBehaviorEnum.ClientMyOrganizationDeletionBehaviorEnumSerializer) +)] +[Serializable] +public readonly record struct ClientMyOrganizationDeletionBehaviorEnum : IStringEnum +{ + public static readonly ClientMyOrganizationDeletionBehaviorEnum Allow = new(Values.Allow); + + public static readonly ClientMyOrganizationDeletionBehaviorEnum AllowIfEmpty = new( + Values.AllowIfEmpty + ); + + public ClientMyOrganizationDeletionBehaviorEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientMyOrganizationDeletionBehaviorEnum FromCustom(string value) + { + return new ClientMyOrganizationDeletionBehaviorEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==( + ClientMyOrganizationDeletionBehaviorEnum value1, + string value2 + ) => value1.Value.Equals(value2); + + public static bool operator !=( + ClientMyOrganizationDeletionBehaviorEnum value1, + string value2 + ) => !value1.Value.Equals(value2); + + public static explicit operator string(ClientMyOrganizationDeletionBehaviorEnum value) => + value.Value; + + public static explicit operator ClientMyOrganizationDeletionBehaviorEnum(string value) => + new(value); + + internal class ClientMyOrganizationDeletionBehaviorEnumSerializer + : JsonConverter + { + public override ClientMyOrganizationDeletionBehaviorEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientMyOrganizationDeletionBehaviorEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientMyOrganizationDeletionBehaviorEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientMyOrganizationDeletionBehaviorEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientMyOrganizationDeletionBehaviorEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientMyOrganizationDeletionBehaviorEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Allow = "allow"; + + public const string AllowIfEmpty = "allow_if_empty"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientMyOrganizationPatchConfiguration.cs b/src/Auth0.ManagementApi/Types/ClientMyOrganizationPatchConfiguration.cs new file mode 100644 index 000000000..0fe202c9c --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientMyOrganizationPatchConfiguration.cs @@ -0,0 +1,52 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +/// +/// Configuration related to the My Organization Configuration for the client. +/// +[Serializable] +public record ClientMyOrganizationPatchConfiguration : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// The connection profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("connection_profile_id")] + public string? ConnectionProfileId { get; set; } + + /// + /// The user attribute profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("user_attribute_profile_id")] + public string? UserAttributeProfileId { get; set; } + + /// + /// The allowed connection strategies for the My Organization Configuration. + /// + [JsonPropertyName("allowed_strategies")] + public IEnumerable AllowedStrategies { get; set; } = + new List(); + + [JsonPropertyName("connection_deletion_behavior")] + public required ClientMyOrganizationDeletionBehaviorEnum ConnectionDeletionBehavior { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientMyOrganizationPostConfiguration.cs b/src/Auth0.ManagementApi/Types/ClientMyOrganizationPostConfiguration.cs new file mode 100644 index 000000000..3ca8791be --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientMyOrganizationPostConfiguration.cs @@ -0,0 +1,52 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +/// +/// Configuration related to the My Organization Configuration for the client. +/// +[Serializable] +public record ClientMyOrganizationPostConfiguration : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// The connection profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("connection_profile_id")] + public string? ConnectionProfileId { get; set; } + + /// + /// The user attribute profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("user_attribute_profile_id")] + public string? UserAttributeProfileId { get; set; } + + /// + /// The allowed connection strategies for the My Organization Configuration. + /// + [JsonPropertyName("allowed_strategies")] + public IEnumerable AllowedStrategies { get; set; } = + new List(); + + [JsonPropertyName("connection_deletion_behavior")] + public required ClientMyOrganizationDeletionBehaviorEnum ConnectionDeletionBehavior { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientMyOrganizationResponseConfiguration.cs b/src/Auth0.ManagementApi/Types/ClientMyOrganizationResponseConfiguration.cs new file mode 100644 index 000000000..f5e11d88b --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientMyOrganizationResponseConfiguration.cs @@ -0,0 +1,52 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +/// +/// Configuration related to the My Organization Configuration for the client. +/// +[Serializable] +public record ClientMyOrganizationResponseConfiguration : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// The connection profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("connection_profile_id")] + public string? ConnectionProfileId { get; set; } + + /// + /// The user attribute profile ID that this client should validate against. + /// + [Optional] + [JsonPropertyName("user_attribute_profile_id")] + public string? UserAttributeProfileId { get; set; } + + /// + /// The allowed connection strategies for the My Organization Configuration. + /// + [JsonPropertyName("allowed_strategies")] + public IEnumerable AllowedStrategies { get; set; } = + new List(); + + [JsonPropertyName("connection_deletion_behavior")] + public required ClientMyOrganizationDeletionBehaviorEnum ConnectionDeletionBehavior { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientRedirectionPolicyEnum.cs b/src/Auth0.ManagementApi/Types/ClientRedirectionPolicyEnum.cs new file mode 100644 index 000000000..cd0bfcb54 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientRedirectionPolicyEnum.cs @@ -0,0 +1,118 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter(typeof(ClientRedirectionPolicyEnum.ClientRedirectionPolicyEnumSerializer))] +[Serializable] +public readonly record struct ClientRedirectionPolicyEnum : IStringEnum +{ + public static readonly ClientRedirectionPolicyEnum AllowAlways = new(Values.AllowAlways); + + public static readonly ClientRedirectionPolicyEnum OpenRedirectProtection = new( + Values.OpenRedirectProtection + ); + + public ClientRedirectionPolicyEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientRedirectionPolicyEnum FromCustom(string value) + { + return new ClientRedirectionPolicyEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==(ClientRedirectionPolicyEnum value1, string value2) => + value1.Value.Equals(value2); + + public static bool operator !=(ClientRedirectionPolicyEnum value1, string value2) => + !value1.Value.Equals(value2); + + public static explicit operator string(ClientRedirectionPolicyEnum value) => value.Value; + + public static explicit operator ClientRedirectionPolicyEnum(string value) => new(value); + + internal class ClientRedirectionPolicyEnumSerializer + : JsonConverter + { + public override ClientRedirectionPolicyEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientRedirectionPolicyEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientRedirectionPolicyEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientRedirectionPolicyEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientRedirectionPolicyEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientRedirectionPolicyEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string AllowAlways = "allow_always"; + + public const string OpenRedirectProtection = "open_redirect_protection"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientSessionTransferConfiguration.cs b/src/Auth0.ManagementApi/Types/ClientSessionTransferConfiguration.cs index dfdcb5db1..e5c9ca88e 100644 --- a/src/Auth0.ManagementApi/Types/ClientSessionTransferConfiguration.cs +++ b/src/Auth0.ManagementApi/Types/ClientSessionTransferConfiguration.cs @@ -53,6 +53,10 @@ public record ClientSessionTransferConfiguration : IJsonOnDeserialized [JsonPropertyName("enforce_online_refresh_tokens")] public bool? EnforceOnlineRefreshTokens { get; set; } + [Nullable, Optional] + [JsonPropertyName("delegation")] + public Optional Delegation { get; set; } + [JsonIgnore] public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); diff --git a/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationConfiguration.cs b/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationConfiguration.cs new file mode 100644 index 000000000..65602773c --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationConfiguration.cs @@ -0,0 +1,39 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +/// +/// Configuration for delegation (impersonation) access using Session Transfer Tokens +/// +[Serializable] +public record ClientSessionTransferDelegationConfiguration : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// Indicates whether delegation (impersonation) access is allowed using Session Transfer Tokens. Default value is `false`. + /// + [Optional] + [JsonPropertyName("allow_delegated_access")] + public bool? AllowDelegatedAccess { get; set; } + + [Optional] + [JsonPropertyName("enforce_device_binding")] + public ClientSessionTransferDelegationDeviceBindingEnum? EnforceDeviceBinding { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationDeviceBindingEnum.cs b/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationDeviceBindingEnum.cs new file mode 100644 index 000000000..7c5bb0575 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientSessionTransferDelegationDeviceBindingEnum.cs @@ -0,0 +1,126 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter( + typeof(ClientSessionTransferDelegationDeviceBindingEnum.ClientSessionTransferDelegationDeviceBindingEnumSerializer) +)] +[Serializable] +public readonly record struct ClientSessionTransferDelegationDeviceBindingEnum : IStringEnum +{ + public static readonly ClientSessionTransferDelegationDeviceBindingEnum Ip = new(Values.Ip); + + public static readonly ClientSessionTransferDelegationDeviceBindingEnum Asn = new(Values.Asn); + + public ClientSessionTransferDelegationDeviceBindingEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientSessionTransferDelegationDeviceBindingEnum FromCustom(string value) + { + return new ClientSessionTransferDelegationDeviceBindingEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==( + ClientSessionTransferDelegationDeviceBindingEnum value1, + string value2 + ) => value1.Value.Equals(value2); + + public static bool operator !=( + ClientSessionTransferDelegationDeviceBindingEnum value1, + string value2 + ) => !value1.Value.Equals(value2); + + public static explicit operator string( + ClientSessionTransferDelegationDeviceBindingEnum value + ) => value.Value; + + public static explicit operator ClientSessionTransferDelegationDeviceBindingEnum( + string value + ) => new(value); + + internal class ClientSessionTransferDelegationDeviceBindingEnumSerializer + : JsonConverter + { + public override ClientSessionTransferDelegationDeviceBindingEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientSessionTransferDelegationDeviceBindingEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientSessionTransferDelegationDeviceBindingEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientSessionTransferDelegationDeviceBindingEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientSessionTransferDelegationDeviceBindingEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientSessionTransferDelegationDeviceBindingEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Ip = "ip"; + + public const string Asn = "asn"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ClientThirdPartySecurityModeEnum.cs b/src/Auth0.ManagementApi/Types/ClientThirdPartySecurityModeEnum.cs new file mode 100644 index 000000000..f50bcae43 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ClientThirdPartySecurityModeEnum.cs @@ -0,0 +1,116 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter(typeof(ClientThirdPartySecurityModeEnum.ClientThirdPartySecurityModeEnumSerializer))] +[Serializable] +public readonly record struct ClientThirdPartySecurityModeEnum : IStringEnum +{ + public static readonly ClientThirdPartySecurityModeEnum Strict = new(Values.Strict); + + public static readonly ClientThirdPartySecurityModeEnum Permissive = new(Values.Permissive); + + public ClientThirdPartySecurityModeEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ClientThirdPartySecurityModeEnum FromCustom(string value) + { + return new ClientThirdPartySecurityModeEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==(ClientThirdPartySecurityModeEnum value1, string value2) => + value1.Value.Equals(value2); + + public static bool operator !=(ClientThirdPartySecurityModeEnum value1, string value2) => + !value1.Value.Equals(value2); + + public static explicit operator string(ClientThirdPartySecurityModeEnum value) => value.Value; + + public static explicit operator ClientThirdPartySecurityModeEnum(string value) => new(value); + + internal class ClientThirdPartySecurityModeEnumSerializer + : JsonConverter + { + public override ClientThirdPartySecurityModeEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ClientThirdPartySecurityModeEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ClientThirdPartySecurityModeEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ClientThirdPartySecurityModeEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ClientThirdPartySecurityModeEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ClientThirdPartySecurityModeEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Strict = "strict"; + + public const string Permissive = "permissive"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ConnectedAccount.cs b/src/Auth0.ManagementApi/Types/ConnectedAccount.cs index 4be6d8a71..c84da8c48 100644 --- a/src/Auth0.ManagementApi/Types/ConnectedAccount.cs +++ b/src/Auth0.ManagementApi/Types/ConnectedAccount.cs @@ -58,6 +58,13 @@ public record ConnectedAccount : IJsonOnDeserialized [JsonPropertyName("expires_at")] public DateTime? ExpiresAt { get; set; } + /// + /// The identifier of the organization associated with the connected account. + /// + [Optional] + [JsonPropertyName("organization_id")] + public string? OrganizationId { get; set; } + [JsonIgnore] public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); diff --git a/src/Auth0.ManagementApi/Types/ConnectionDpopSigningAlgEnum.cs b/src/Auth0.ManagementApi/Types/ConnectionDpopSigningAlgEnum.cs new file mode 100644 index 000000000..7e0b06920 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ConnectionDpopSigningAlgEnum.cs @@ -0,0 +1,116 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter(typeof(ConnectionDpopSigningAlgEnum.ConnectionDpopSigningAlgEnumSerializer))] +[Serializable] +public readonly record struct ConnectionDpopSigningAlgEnum : IStringEnum +{ + public static readonly ConnectionDpopSigningAlgEnum Es256 = new(Values.Es256); + + public static readonly ConnectionDpopSigningAlgEnum Ed25519 = new(Values.Ed25519); + + public ConnectionDpopSigningAlgEnum(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static ConnectionDpopSigningAlgEnum FromCustom(string value) + { + return new ConnectionDpopSigningAlgEnum(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==(ConnectionDpopSigningAlgEnum value1, string value2) => + value1.Value.Equals(value2); + + public static bool operator !=(ConnectionDpopSigningAlgEnum value1, string value2) => + !value1.Value.Equals(value2); + + public static explicit operator string(ConnectionDpopSigningAlgEnum value) => value.Value; + + public static explicit operator ConnectionDpopSigningAlgEnum(string value) => new(value); + + internal class ConnectionDpopSigningAlgEnumSerializer + : JsonConverter + { + public override ConnectionDpopSigningAlgEnum Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new ConnectionDpopSigningAlgEnum(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + ConnectionDpopSigningAlgEnum value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override ConnectionDpopSigningAlgEnum ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new ConnectionDpopSigningAlgEnum(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + ConnectionDpopSigningAlgEnum value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Es256 = "ES256"; + + public const string Ed25519 = "Ed25519"; + } +} diff --git a/src/Auth0.ManagementApi/Types/ConnectionOptionsCommonOidc.cs b/src/Auth0.ManagementApi/Types/ConnectionOptionsCommonOidc.cs index af5e1bbbe..f6b59dcaa 100644 --- a/src/Auth0.ManagementApi/Types/ConnectionOptionsCommonOidc.cs +++ b/src/Auth0.ManagementApi/Types/ConnectionOptionsCommonOidc.cs @@ -32,6 +32,10 @@ public record ConnectionOptionsCommonOidc : IJsonOnDeserialized, IJsonOnSerializ [JsonPropertyName("domain_aliases")] public IEnumerable? DomainAliases { get; set; } + [Optional] + [JsonPropertyName("dpop_signing_alg")] + public ConnectionDpopSigningAlgEnum? DpopSigningAlg { get; set; } + [Nullable, Optional] [JsonPropertyName("federated_connections_access_tokens")] public Optional FederatedConnectionsAccessTokens { get; set; } diff --git a/src/Auth0.ManagementApi/Types/ConnectionOptionsOidc.cs b/src/Auth0.ManagementApi/Types/ConnectionOptionsOidc.cs index a7b7b1639..55f7d7e91 100644 --- a/src/Auth0.ManagementApi/Types/ConnectionOptionsOidc.cs +++ b/src/Auth0.ManagementApi/Types/ConnectionOptionsOidc.cs @@ -44,6 +44,10 @@ public record ConnectionOptionsOidc : IJsonOnDeserialized, IJsonOnSerializing [JsonPropertyName("domain_aliases")] public IEnumerable? DomainAliases { get; set; } + [Optional] + [JsonPropertyName("dpop_signing_alg")] + public ConnectionDpopSigningAlgEnum? DpopSigningAlg { get; set; } + [Nullable, Optional] [JsonPropertyName("federated_connections_access_tokens")] public Optional FederatedConnectionsAccessTokens { get; set; } diff --git a/src/Auth0.ManagementApi/Types/ConnectionOptionsOkta.cs b/src/Auth0.ManagementApi/Types/ConnectionOptionsOkta.cs index f4186cde0..381089e02 100644 --- a/src/Auth0.ManagementApi/Types/ConnectionOptionsOkta.cs +++ b/src/Auth0.ManagementApi/Types/ConnectionOptionsOkta.cs @@ -48,6 +48,10 @@ public record ConnectionOptionsOkta : IJsonOnDeserialized, IJsonOnSerializing [JsonPropertyName("domain_aliases")] public IEnumerable? DomainAliases { get; set; } + [Optional] + [JsonPropertyName("dpop_signing_alg")] + public ConnectionDpopSigningAlgEnum? DpopSigningAlg { get; set; } + [Nullable, Optional] [JsonPropertyName("federated_connections_access_tokens")] public Optional FederatedConnectionsAccessTokens { get; set; } diff --git a/src/Auth0.ManagementApi/Types/ConnectionPropertiesOptions.cs b/src/Auth0.ManagementApi/Types/ConnectionPropertiesOptions.cs index f9d0b7b6d..20e158895 100644 --- a/src/Auth0.ManagementApi/Types/ConnectionPropertiesOptions.cs +++ b/src/Auth0.ManagementApi/Types/ConnectionPropertiesOptions.cs @@ -99,6 +99,10 @@ public record ConnectionPropertiesOptions : IJsonOnDeserialized, IJsonOnSerializ [JsonPropertyName("api_enable_users")] public bool? ApiEnableUsers { get; set; } + [Optional] + [JsonPropertyName("api_enable_groups")] + public bool? ApiEnableGroups { get; set; } + [Optional] [JsonPropertyName("basic_profile")] public bool? BasicProfile { get; set; } diff --git a/src/Auth0.ManagementApi/Types/CreateClientGrantResponseContent.cs b/src/Auth0.ManagementApi/Types/CreateClientGrantResponseContent.cs index 6c6d8b4df..54fe90ad5 100644 --- a/src/Auth0.ManagementApi/Types/CreateClientGrantResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/CreateClientGrantResponseContent.cs @@ -50,6 +50,10 @@ public record CreateClientGrantResponseContent : IJsonOnDeserialized [JsonPropertyName("allow_any_organization")] public bool? AllowAnyOrganization { get; set; } + [Optional] + [JsonPropertyName("default_for")] + public ClientGrantDefaultForEnum? DefaultFor { get; set; } + /// /// If enabled, this grant is a special grant created by Auth0. It cannot be modified or deleted directly. /// diff --git a/src/Auth0.ManagementApi/Types/CreateClientResponseContent.cs b/src/Auth0.ManagementApi/Types/CreateClientResponseContent.cs index 1e146f2b6..348f9d7dc 100644 --- a/src/Auth0.ManagementApi/Types/CreateClientResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/CreateClientResponseContent.cs @@ -309,6 +309,18 @@ public record CreateClientResponseContent : IJsonOnDeserialized, IJsonOnSerializ [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationResponseConfiguration? MyOrganizationConfiguration { get; set; } + + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// /// The identifier of the resource server that this client is linked to. /// diff --git a/src/Auth0.ManagementApi/Types/EventStreamDeliveryEventTypeEnum.cs b/src/Auth0.ManagementApi/Types/EventStreamDeliveryEventTypeEnum.cs index 8356044f5..d7eb466eb 100644 --- a/src/Auth0.ManagementApi/Types/EventStreamDeliveryEventTypeEnum.cs +++ b/src/Auth0.ManagementApi/Types/EventStreamDeliveryEventTypeEnum.cs @@ -8,24 +8,56 @@ namespace Auth0.ManagementApi; [Serializable] public readonly record struct EventStreamDeliveryEventTypeEnum : IStringEnum { - public static readonly EventStreamDeliveryEventTypeEnum UserCreated = new(Values.UserCreated); + public static readonly EventStreamDeliveryEventTypeEnum GroupCreated = new(Values.GroupCreated); - public static readonly EventStreamDeliveryEventTypeEnum UserDeleted = new(Values.UserDeleted); + public static readonly EventStreamDeliveryEventTypeEnum GroupDeleted = new(Values.GroupDeleted); - public static readonly EventStreamDeliveryEventTypeEnum UserUpdated = new(Values.UserUpdated); + public static readonly EventStreamDeliveryEventTypeEnum GroupMemberAdded = new( + Values.GroupMemberAdded + ); - public static readonly EventStreamDeliveryEventTypeEnum OrganizationCreated = new( - Values.OrganizationCreated + public static readonly EventStreamDeliveryEventTypeEnum GroupMemberDeleted = new( + Values.GroupMemberDeleted ); - public static readonly EventStreamDeliveryEventTypeEnum OrganizationUpdated = new( - Values.OrganizationUpdated + public static readonly EventStreamDeliveryEventTypeEnum GroupRoleAssigned = new( + Values.GroupRoleAssigned + ); + + public static readonly EventStreamDeliveryEventTypeEnum GroupRoleDeleted = new( + Values.GroupRoleDeleted + ); + + public static readonly EventStreamDeliveryEventTypeEnum GroupUpdated = new(Values.GroupUpdated); + + public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionAdded = new( + Values.OrganizationConnectionAdded + ); + + public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionRemoved = new( + Values.OrganizationConnectionRemoved + ); + + public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionUpdated = new( + Values.OrganizationConnectionUpdated + ); + + public static readonly EventStreamDeliveryEventTypeEnum OrganizationCreated = new( + Values.OrganizationCreated ); public static readonly EventStreamDeliveryEventTypeEnum OrganizationDeleted = new( Values.OrganizationDeleted ); + public static readonly EventStreamDeliveryEventTypeEnum OrganizationGroupRoleAssigned = new( + Values.OrganizationGroupRoleAssigned + ); + + public static readonly EventStreamDeliveryEventTypeEnum OrganizationGroupRoleDeleted = new( + Values.OrganizationGroupRoleDeleted + ); + public static readonly EventStreamDeliveryEventTypeEnum OrganizationMemberAdded = new( Values.OrganizationMemberAdded ); @@ -42,31 +74,15 @@ namespace Auth0.ManagementApi; Values.OrganizationMemberRoleDeleted ); - public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionAdded = new( - Values.OrganizationConnectionAdded - ); - - public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionUpdated = new( - Values.OrganizationConnectionUpdated - ); - - public static readonly EventStreamDeliveryEventTypeEnum OrganizationConnectionRemoved = new( - Values.OrganizationConnectionRemoved + public static readonly EventStreamDeliveryEventTypeEnum OrganizationUpdated = new( + Values.OrganizationUpdated ); - public static readonly EventStreamDeliveryEventTypeEnum GroupCreated = new(Values.GroupCreated); - - public static readonly EventStreamDeliveryEventTypeEnum GroupUpdated = new(Values.GroupUpdated); - - public static readonly EventStreamDeliveryEventTypeEnum GroupDeleted = new(Values.GroupDeleted); + public static readonly EventStreamDeliveryEventTypeEnum UserCreated = new(Values.UserCreated); - public static readonly EventStreamDeliveryEventTypeEnum GroupMemberAdded = new( - Values.GroupMemberAdded - ); + public static readonly EventStreamDeliveryEventTypeEnum UserDeleted = new(Values.UserDeleted); - public static readonly EventStreamDeliveryEventTypeEnum GroupMemberDeleted = new( - Values.GroupMemberDeleted - ); + public static readonly EventStreamDeliveryEventTypeEnum UserUpdated = new(Values.UserUpdated); public EventStreamDeliveryEventTypeEnum(string value) { @@ -165,18 +181,34 @@ JsonSerializerOptions options [Serializable] public static class Values { - public const string UserCreated = "user.created"; + public const string GroupCreated = "group.created"; - public const string UserDeleted = "user.deleted"; + public const string GroupDeleted = "group.deleted"; - public const string UserUpdated = "user.updated"; + public const string GroupMemberAdded = "group.member.added"; - public const string OrganizationCreated = "organization.created"; + public const string GroupMemberDeleted = "group.member.deleted"; - public const string OrganizationUpdated = "organization.updated"; + public const string GroupRoleAssigned = "group.role.assigned"; + + public const string GroupRoleDeleted = "group.role.deleted"; + + public const string GroupUpdated = "group.updated"; + + public const string OrganizationConnectionAdded = "organization.connection.added"; + + public const string OrganizationConnectionRemoved = "organization.connection.removed"; + + public const string OrganizationConnectionUpdated = "organization.connection.updated"; + + public const string OrganizationCreated = "organization.created"; public const string OrganizationDeleted = "organization.deleted"; + public const string OrganizationGroupRoleAssigned = "organization.group.role.assigned"; + + public const string OrganizationGroupRoleDeleted = "organization.group.role.deleted"; + public const string OrganizationMemberAdded = "organization.member.added"; public const string OrganizationMemberDeleted = "organization.member.deleted"; @@ -185,20 +217,12 @@ public static class Values public const string OrganizationMemberRoleDeleted = "organization.member.role.deleted"; - public const string OrganizationConnectionAdded = "organization.connection.added"; - - public const string OrganizationConnectionUpdated = "organization.connection.updated"; - - public const string OrganizationConnectionRemoved = "organization.connection.removed"; - - public const string GroupCreated = "group.created"; - - public const string GroupUpdated = "group.updated"; + public const string OrganizationUpdated = "organization.updated"; - public const string GroupDeleted = "group.deleted"; + public const string UserCreated = "user.created"; - public const string GroupMemberAdded = "group.member.added"; + public const string UserDeleted = "user.deleted"; - public const string GroupMemberDeleted = "group.member.deleted"; + public const string UserUpdated = "user.updated"; } } diff --git a/src/Auth0.ManagementApi/Types/EventStreamEventTypeEnum.cs b/src/Auth0.ManagementApi/Types/EventStreamEventTypeEnum.cs index ef758c852..99d1e53cd 100644 --- a/src/Auth0.ManagementApi/Types/EventStreamEventTypeEnum.cs +++ b/src/Auth0.ManagementApi/Types/EventStreamEventTypeEnum.cs @@ -8,24 +8,52 @@ namespace Auth0.ManagementApi; [Serializable] public readonly record struct EventStreamEventTypeEnum : IStringEnum { - public static readonly EventStreamEventTypeEnum UserCreated = new(Values.UserCreated); + public static readonly EventStreamEventTypeEnum GroupCreated = new(Values.GroupCreated); - public static readonly EventStreamEventTypeEnum UserDeleted = new(Values.UserDeleted); + public static readonly EventStreamEventTypeEnum GroupDeleted = new(Values.GroupDeleted); - public static readonly EventStreamEventTypeEnum UserUpdated = new(Values.UserUpdated); + public static readonly EventStreamEventTypeEnum GroupMemberAdded = new(Values.GroupMemberAdded); - public static readonly EventStreamEventTypeEnum OrganizationCreated = new( - Values.OrganizationCreated + public static readonly EventStreamEventTypeEnum GroupMemberDeleted = new( + Values.GroupMemberDeleted ); - public static readonly EventStreamEventTypeEnum OrganizationUpdated = new( - Values.OrganizationUpdated + public static readonly EventStreamEventTypeEnum GroupRoleAssigned = new( + Values.GroupRoleAssigned + ); + + public static readonly EventStreamEventTypeEnum GroupRoleDeleted = new(Values.GroupRoleDeleted); + + public static readonly EventStreamEventTypeEnum GroupUpdated = new(Values.GroupUpdated); + + public static readonly EventStreamEventTypeEnum OrganizationConnectionAdded = new( + Values.OrganizationConnectionAdded + ); + + public static readonly EventStreamEventTypeEnum OrganizationConnectionRemoved = new( + Values.OrganizationConnectionRemoved + ); + + public static readonly EventStreamEventTypeEnum OrganizationConnectionUpdated = new( + Values.OrganizationConnectionUpdated + ); + + public static readonly EventStreamEventTypeEnum OrganizationCreated = new( + Values.OrganizationCreated ); public static readonly EventStreamEventTypeEnum OrganizationDeleted = new( Values.OrganizationDeleted ); + public static readonly EventStreamEventTypeEnum OrganizationGroupRoleAssigned = new( + Values.OrganizationGroupRoleAssigned + ); + + public static readonly EventStreamEventTypeEnum OrganizationGroupRoleDeleted = new( + Values.OrganizationGroupRoleDeleted + ); + public static readonly EventStreamEventTypeEnum OrganizationMemberAdded = new( Values.OrganizationMemberAdded ); @@ -42,29 +70,15 @@ namespace Auth0.ManagementApi; Values.OrganizationMemberRoleDeleted ); - public static readonly EventStreamEventTypeEnum OrganizationConnectionAdded = new( - Values.OrganizationConnectionAdded - ); - - public static readonly EventStreamEventTypeEnum OrganizationConnectionUpdated = new( - Values.OrganizationConnectionUpdated - ); - - public static readonly EventStreamEventTypeEnum OrganizationConnectionRemoved = new( - Values.OrganizationConnectionRemoved + public static readonly EventStreamEventTypeEnum OrganizationUpdated = new( + Values.OrganizationUpdated ); - public static readonly EventStreamEventTypeEnum GroupCreated = new(Values.GroupCreated); - - public static readonly EventStreamEventTypeEnum GroupUpdated = new(Values.GroupUpdated); - - public static readonly EventStreamEventTypeEnum GroupDeleted = new(Values.GroupDeleted); + public static readonly EventStreamEventTypeEnum UserCreated = new(Values.UserCreated); - public static readonly EventStreamEventTypeEnum GroupMemberAdded = new(Values.GroupMemberAdded); + public static readonly EventStreamEventTypeEnum UserDeleted = new(Values.UserDeleted); - public static readonly EventStreamEventTypeEnum GroupMemberDeleted = new( - Values.GroupMemberDeleted - ); + public static readonly EventStreamEventTypeEnum UserUpdated = new(Values.UserUpdated); public EventStreamEventTypeEnum(string value) { @@ -162,18 +176,34 @@ JsonSerializerOptions options [Serializable] public static class Values { - public const string UserCreated = "user.created"; + public const string GroupCreated = "group.created"; - public const string UserDeleted = "user.deleted"; + public const string GroupDeleted = "group.deleted"; - public const string UserUpdated = "user.updated"; + public const string GroupMemberAdded = "group.member.added"; - public const string OrganizationCreated = "organization.created"; + public const string GroupMemberDeleted = "group.member.deleted"; - public const string OrganizationUpdated = "organization.updated"; + public const string GroupRoleAssigned = "group.role.assigned"; + + public const string GroupRoleDeleted = "group.role.deleted"; + + public const string GroupUpdated = "group.updated"; + + public const string OrganizationConnectionAdded = "organization.connection.added"; + + public const string OrganizationConnectionRemoved = "organization.connection.removed"; + + public const string OrganizationConnectionUpdated = "organization.connection.updated"; + + public const string OrganizationCreated = "organization.created"; public const string OrganizationDeleted = "organization.deleted"; + public const string OrganizationGroupRoleAssigned = "organization.group.role.assigned"; + + public const string OrganizationGroupRoleDeleted = "organization.group.role.deleted"; + public const string OrganizationMemberAdded = "organization.member.added"; public const string OrganizationMemberDeleted = "organization.member.deleted"; @@ -182,20 +212,12 @@ public static class Values public const string OrganizationMemberRoleDeleted = "organization.member.role.deleted"; - public const string OrganizationConnectionAdded = "organization.connection.added"; - - public const string OrganizationConnectionUpdated = "organization.connection.updated"; - - public const string OrganizationConnectionRemoved = "organization.connection.removed"; - - public const string GroupCreated = "group.created"; - - public const string GroupUpdated = "group.updated"; + public const string OrganizationUpdated = "organization.updated"; - public const string GroupDeleted = "group.deleted"; + public const string UserCreated = "user.created"; - public const string GroupMemberAdded = "group.member.added"; + public const string UserDeleted = "user.deleted"; - public const string GroupMemberDeleted = "group.member.deleted"; + public const string UserUpdated = "user.updated"; } } diff --git a/src/Auth0.ManagementApi/Types/EventStreamTestEventTypeEnum.cs b/src/Auth0.ManagementApi/Types/EventStreamTestEventTypeEnum.cs index 1aa3f44ed..f1ccb5fac 100644 --- a/src/Auth0.ManagementApi/Types/EventStreamTestEventTypeEnum.cs +++ b/src/Auth0.ManagementApi/Types/EventStreamTestEventTypeEnum.cs @@ -8,24 +8,56 @@ namespace Auth0.ManagementApi; [Serializable] public readonly record struct EventStreamTestEventTypeEnum : IStringEnum { - public static readonly EventStreamTestEventTypeEnum UserCreated = new(Values.UserCreated); + public static readonly EventStreamTestEventTypeEnum GroupCreated = new(Values.GroupCreated); - public static readonly EventStreamTestEventTypeEnum UserDeleted = new(Values.UserDeleted); + public static readonly EventStreamTestEventTypeEnum GroupDeleted = new(Values.GroupDeleted); - public static readonly EventStreamTestEventTypeEnum UserUpdated = new(Values.UserUpdated); + public static readonly EventStreamTestEventTypeEnum GroupMemberAdded = new( + Values.GroupMemberAdded + ); - public static readonly EventStreamTestEventTypeEnum OrganizationCreated = new( - Values.OrganizationCreated + public static readonly EventStreamTestEventTypeEnum GroupMemberDeleted = new( + Values.GroupMemberDeleted ); - public static readonly EventStreamTestEventTypeEnum OrganizationUpdated = new( - Values.OrganizationUpdated + public static readonly EventStreamTestEventTypeEnum GroupRoleAssigned = new( + Values.GroupRoleAssigned + ); + + public static readonly EventStreamTestEventTypeEnum GroupRoleDeleted = new( + Values.GroupRoleDeleted + ); + + public static readonly EventStreamTestEventTypeEnum GroupUpdated = new(Values.GroupUpdated); + + public static readonly EventStreamTestEventTypeEnum OrganizationConnectionAdded = new( + Values.OrganizationConnectionAdded + ); + + public static readonly EventStreamTestEventTypeEnum OrganizationConnectionRemoved = new( + Values.OrganizationConnectionRemoved + ); + + public static readonly EventStreamTestEventTypeEnum OrganizationConnectionUpdated = new( + Values.OrganizationConnectionUpdated + ); + + public static readonly EventStreamTestEventTypeEnum OrganizationCreated = new( + Values.OrganizationCreated ); public static readonly EventStreamTestEventTypeEnum OrganizationDeleted = new( Values.OrganizationDeleted ); + public static readonly EventStreamTestEventTypeEnum OrganizationGroupRoleAssigned = new( + Values.OrganizationGroupRoleAssigned + ); + + public static readonly EventStreamTestEventTypeEnum OrganizationGroupRoleDeleted = new( + Values.OrganizationGroupRoleDeleted + ); + public static readonly EventStreamTestEventTypeEnum OrganizationMemberAdded = new( Values.OrganizationMemberAdded ); @@ -42,31 +74,15 @@ namespace Auth0.ManagementApi; Values.OrganizationMemberRoleDeleted ); - public static readonly EventStreamTestEventTypeEnum OrganizationConnectionAdded = new( - Values.OrganizationConnectionAdded - ); - - public static readonly EventStreamTestEventTypeEnum OrganizationConnectionUpdated = new( - Values.OrganizationConnectionUpdated - ); - - public static readonly EventStreamTestEventTypeEnum OrganizationConnectionRemoved = new( - Values.OrganizationConnectionRemoved + public static readonly EventStreamTestEventTypeEnum OrganizationUpdated = new( + Values.OrganizationUpdated ); - public static readonly EventStreamTestEventTypeEnum GroupCreated = new(Values.GroupCreated); - - public static readonly EventStreamTestEventTypeEnum GroupUpdated = new(Values.GroupUpdated); - - public static readonly EventStreamTestEventTypeEnum GroupDeleted = new(Values.GroupDeleted); + public static readonly EventStreamTestEventTypeEnum UserCreated = new(Values.UserCreated); - public static readonly EventStreamTestEventTypeEnum GroupMemberAdded = new( - Values.GroupMemberAdded - ); + public static readonly EventStreamTestEventTypeEnum UserDeleted = new(Values.UserDeleted); - public static readonly EventStreamTestEventTypeEnum GroupMemberDeleted = new( - Values.GroupMemberDeleted - ); + public static readonly EventStreamTestEventTypeEnum UserUpdated = new(Values.UserUpdated); public EventStreamTestEventTypeEnum(string value) { @@ -165,18 +181,34 @@ JsonSerializerOptions options [Serializable] public static class Values { - public const string UserCreated = "user.created"; + public const string GroupCreated = "group.created"; - public const string UserDeleted = "user.deleted"; + public const string GroupDeleted = "group.deleted"; - public const string UserUpdated = "user.updated"; + public const string GroupMemberAdded = "group.member.added"; - public const string OrganizationCreated = "organization.created"; + public const string GroupMemberDeleted = "group.member.deleted"; - public const string OrganizationUpdated = "organization.updated"; + public const string GroupRoleAssigned = "group.role.assigned"; + + public const string GroupRoleDeleted = "group.role.deleted"; + + public const string GroupUpdated = "group.updated"; + + public const string OrganizationConnectionAdded = "organization.connection.added"; + + public const string OrganizationConnectionRemoved = "organization.connection.removed"; + + public const string OrganizationConnectionUpdated = "organization.connection.updated"; + + public const string OrganizationCreated = "organization.created"; public const string OrganizationDeleted = "organization.deleted"; + public const string OrganizationGroupRoleAssigned = "organization.group.role.assigned"; + + public const string OrganizationGroupRoleDeleted = "organization.group.role.deleted"; + public const string OrganizationMemberAdded = "organization.member.added"; public const string OrganizationMemberDeleted = "organization.member.deleted"; @@ -185,20 +217,12 @@ public static class Values public const string OrganizationMemberRoleDeleted = "organization.member.role.deleted"; - public const string OrganizationConnectionAdded = "organization.connection.added"; - - public const string OrganizationConnectionUpdated = "organization.connection.updated"; - - public const string OrganizationConnectionRemoved = "organization.connection.removed"; - - public const string GroupCreated = "group.created"; - - public const string GroupUpdated = "group.updated"; + public const string OrganizationUpdated = "organization.updated"; - public const string GroupDeleted = "group.deleted"; + public const string UserCreated = "user.created"; - public const string GroupMemberAdded = "group.member.added"; + public const string UserDeleted = "user.deleted"; - public const string GroupMemberDeleted = "group.member.deleted"; + public const string UserUpdated = "user.updated"; } } diff --git a/src/Auth0.ManagementApi/Types/GetClientGrantResponseContent.cs b/src/Auth0.ManagementApi/Types/GetClientGrantResponseContent.cs index 11f1f06da..3913c2e32 100644 --- a/src/Auth0.ManagementApi/Types/GetClientGrantResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/GetClientGrantResponseContent.cs @@ -50,6 +50,10 @@ public record GetClientGrantResponseContent : IJsonOnDeserialized [JsonPropertyName("allow_any_organization")] public bool? AllowAnyOrganization { get; set; } + [Optional] + [JsonPropertyName("default_for")] + public ClientGrantDefaultForEnum? DefaultFor { get; set; } + /// /// If enabled, this grant is a special grant created by Auth0. It cannot be modified or deleted directly. /// diff --git a/src/Auth0.ManagementApi/Types/GetClientResponseContent.cs b/src/Auth0.ManagementApi/Types/GetClientResponseContent.cs index 0e0bee97f..5f5bb12c4 100644 --- a/src/Auth0.ManagementApi/Types/GetClientResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/GetClientResponseContent.cs @@ -309,6 +309,18 @@ public record GetClientResponseContent : IJsonOnDeserialized, IJsonOnSerializing [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationResponseConfiguration? MyOrganizationConfiguration { get; set; } + + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// /// The identifier of the resource server that this client is linked to. /// diff --git a/src/Auth0.ManagementApi/Types/GetTenantSettingsResponseContent.cs b/src/Auth0.ManagementApi/Types/GetTenantSettingsResponseContent.cs index bb85fc94b..d3392dc32 100644 --- a/src/Auth0.ManagementApi/Types/GetTenantSettingsResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/GetTenantSettingsResponseContent.cs @@ -211,6 +211,13 @@ public record GetTenantSettingsResponseContent : IJsonOnDeserialized [JsonPropertyName("resource_parameter_profile")] public TenantSettingsResourceParameterProfile? ResourceParameterProfile { get; set; } + /// + /// Whether the authorization server supports retrieving client metadata from a client_id URL. + /// + [Optional] + [JsonPropertyName("client_id_metadata_document_supported")] + public bool? ClientIdMetadataDocumentSupported { get; set; } + /// /// Whether Phone Consolidated Experience is enabled for this tenant. /// @@ -225,6 +232,10 @@ public record GetTenantSettingsResponseContent : IJsonOnDeserialized [JsonPropertyName("enable_ai_guide")] public bool? EnableAiGuide { get; set; } + [Optional] + [JsonPropertyName("dynamic_client_registration_security_mode")] + public TenantSettingsDynamicClientRegistrationSecurityMode? DynamicClientRegistrationSecurityMode { get; set; } + [JsonIgnore] public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); diff --git a/src/Auth0.ManagementApi/Types/ListSynchronizedGroupsResponseContent.cs b/src/Auth0.ManagementApi/Types/ListSynchronizedGroupsResponseContent.cs new file mode 100644 index 000000000..7e9c3649c --- /dev/null +++ b/src/Auth0.ManagementApi/Types/ListSynchronizedGroupsResponseContent.cs @@ -0,0 +1,39 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[Serializable] +public record ListSynchronizedGroupsResponseContent : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// Array of Google Workspace group ids configured for synchronization. + /// + [JsonPropertyName("groups")] + public IEnumerable Groups { get; set; } = + new List(); + + /// + /// The cursor to be used as the "from" query parameter for the next page of results. + /// + [Optional] + [JsonPropertyName("next")] + public string? Next { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/NetworkAclMatch.cs b/src/Auth0.ManagementApi/Types/NetworkAclMatch.cs index 2d914e27a..0ce291e53 100644 --- a/src/Auth0.ManagementApi/Types/NetworkAclMatch.cs +++ b/src/Auth0.ManagementApi/Types/NetworkAclMatch.cs @@ -15,10 +15,6 @@ public record NetworkAclMatch : IJsonOnDeserialized [JsonPropertyName("asns")] public IEnumerable? Asns { get; set; } - [Optional] - [JsonPropertyName("auth0_managed")] - public IEnumerable? Auth0Managed { get; set; } - [Optional] [JsonPropertyName("geo_country_codes")] public IEnumerable? GeoCountryCodes { get; set; } diff --git a/src/Auth0.ManagementApi/Types/RotateClientSecretResponseContent.cs b/src/Auth0.ManagementApi/Types/RotateClientSecretResponseContent.cs index a4022ad65..6ab209dca 100644 --- a/src/Auth0.ManagementApi/Types/RotateClientSecretResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/RotateClientSecretResponseContent.cs @@ -309,6 +309,18 @@ public record RotateClientSecretResponseContent : IJsonOnDeserialized, IJsonOnSe [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationResponseConfiguration? MyOrganizationConfiguration { get; set; } + + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// /// The identifier of the resource server that this client is linked to. /// diff --git a/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketDomainAliasesConfig.cs b/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketDomainAliasesConfig.cs index ea2b634fe..c1c17eaaa 100644 --- a/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketDomainAliasesConfig.cs +++ b/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketDomainAliasesConfig.cs @@ -17,6 +17,13 @@ public record SelfServiceProfileSsoTicketDomainAliasesConfig : IJsonOnDeserializ [JsonPropertyName("domain_verification")] public required SelfServiceProfileSsoTicketDomainVerificationEnum DomainVerification { get; set; } + /// + /// List of domains that will be submitted for verification during the self-service SSO flow. + /// + [Optional] + [JsonPropertyName("pending_domains")] + public IEnumerable? PendingDomains { get; set; } + [JsonIgnore] public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); diff --git a/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketEnabledFeatures.cs b/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketEnabledFeatures.cs new file mode 100644 index 000000000..b5910d23d --- /dev/null +++ b/src/Auth0.ManagementApi/Types/SelfServiceProfileSsoTicketEnabledFeatures.cs @@ -0,0 +1,49 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +/// +/// Specifies which features are enabled for an "edit connection" ticket. Only applicable when connection ID is provided. +/// +[Serializable] +public record SelfServiceProfileSsoTicketEnabledFeatures : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// Whether SSO configuration is enabled in this ticket. + /// + [Optional] + [JsonPropertyName("sso")] + public bool? Sso { get; set; } + + /// + /// Whether domain verification is enabled in this ticket. + /// + [Optional] + [JsonPropertyName("domain_verification")] + public bool? DomainVerification { get; set; } + + /// + /// Whether provisioning configuration is enabled in this ticket. + /// + [Optional] + [JsonPropertyName("provisioning")] + public bool? Provisioning { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/SynchronizeGroupsEnum.cs b/src/Auth0.ManagementApi/Types/SynchronizeGroupsEnum.cs index cc5edfb41..0f11cad00 100644 --- a/src/Auth0.ManagementApi/Types/SynchronizeGroupsEnum.cs +++ b/src/Auth0.ManagementApi/Types/SynchronizeGroupsEnum.cs @@ -12,6 +12,8 @@ namespace Auth0.ManagementApi; public static readonly SynchronizeGroupsEnum Off = new(Values.Off); + public static readonly SynchronizeGroupsEnum Selected = new(Values.Selected); + public SynchronizeGroupsEnum(string value) { Value = value; @@ -111,5 +113,7 @@ public static class Values public const string All = "all"; public const string Off = "off"; + + public const string Selected = "selected"; } } diff --git a/src/Auth0.ManagementApi/Types/SynchronizedGroupPayload.cs b/src/Auth0.ManagementApi/Types/SynchronizedGroupPayload.cs new file mode 100644 index 000000000..dc5ff882a --- /dev/null +++ b/src/Auth0.ManagementApi/Types/SynchronizedGroupPayload.cs @@ -0,0 +1,31 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[Serializable] +public record SynchronizedGroupPayload : IJsonOnDeserialized +{ + [JsonExtensionData] + private readonly IDictionary _extensionData = + new Dictionary(); + + /// + /// Google Workspace Directory group ID. + /// + [JsonPropertyName("id")] + public required string Id { get; set; } + + [JsonIgnore] + public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); + + void IJsonOnDeserialized.OnDeserialized() => + AdditionalProperties.CopyFromExtensionData(_extensionData); + + /// + public override string ToString() + { + return JsonUtils.Serialize(this); + } +} diff --git a/src/Auth0.ManagementApi/Types/TenantSettingsDynamicClientRegistrationSecurityMode.cs b/src/Auth0.ManagementApi/Types/TenantSettingsDynamicClientRegistrationSecurityMode.cs new file mode 100644 index 000000000..706da79e7 --- /dev/null +++ b/src/Auth0.ManagementApi/Types/TenantSettingsDynamicClientRegistrationSecurityMode.cs @@ -0,0 +1,130 @@ +using Auth0.ManagementApi.Core; +using global::System.Text.Json; +using global::System.Text.Json.Serialization; + +namespace Auth0.ManagementApi; + +[JsonConverter( + typeof(TenantSettingsDynamicClientRegistrationSecurityMode.TenantSettingsDynamicClientRegistrationSecurityModeSerializer) +)] +[Serializable] +public readonly record struct TenantSettingsDynamicClientRegistrationSecurityMode : IStringEnum +{ + public static readonly TenantSettingsDynamicClientRegistrationSecurityMode Strict = new( + Values.Strict + ); + + public static readonly TenantSettingsDynamicClientRegistrationSecurityMode Permissive = new( + Values.Permissive + ); + + public TenantSettingsDynamicClientRegistrationSecurityMode(string value) + { + Value = value; + } + + /// + /// The string value of the enum. + /// + public string Value { get; } + + /// + /// Create a string enum with the given value. + /// + public static TenantSettingsDynamicClientRegistrationSecurityMode FromCustom(string value) + { + return new TenantSettingsDynamicClientRegistrationSecurityMode(value); + } + + public bool Equals(string? other) + { + return Value.Equals(other); + } + + /// + /// Returns the string value of the enum. + /// + public override string ToString() + { + return Value; + } + + public static bool operator ==( + TenantSettingsDynamicClientRegistrationSecurityMode value1, + string value2 + ) => value1.Value.Equals(value2); + + public static bool operator !=( + TenantSettingsDynamicClientRegistrationSecurityMode value1, + string value2 + ) => !value1.Value.Equals(value2); + + public static explicit operator string( + TenantSettingsDynamicClientRegistrationSecurityMode value + ) => value.Value; + + public static explicit operator TenantSettingsDynamicClientRegistrationSecurityMode( + string value + ) => new(value); + + internal class TenantSettingsDynamicClientRegistrationSecurityModeSerializer + : JsonConverter + { + public override TenantSettingsDynamicClientRegistrationSecurityMode Read( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON value could not be read as a string." + ); + return new TenantSettingsDynamicClientRegistrationSecurityMode(stringValue); + } + + public override void Write( + Utf8JsonWriter writer, + TenantSettingsDynamicClientRegistrationSecurityMode value, + JsonSerializerOptions options + ) + { + writer.WriteStringValue(value.Value); + } + + public override TenantSettingsDynamicClientRegistrationSecurityMode ReadAsPropertyName( + ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options + ) + { + var stringValue = + reader.GetString() + ?? throw new global::System.Exception( + "The JSON property name could not be read as a string." + ); + return new TenantSettingsDynamicClientRegistrationSecurityMode(stringValue); + } + + public override void WriteAsPropertyName( + Utf8JsonWriter writer, + TenantSettingsDynamicClientRegistrationSecurityMode value, + JsonSerializerOptions options + ) + { + writer.WritePropertyName(value.Value); + } + } + + /// + /// Constant strings for enum values + /// + [Serializable] + public static class Values + { + public const string Strict = "strict"; + + public const string Permissive = "permissive"; + } +} diff --git a/src/Auth0.ManagementApi/Types/UpdateClientGrantResponseContent.cs b/src/Auth0.ManagementApi/Types/UpdateClientGrantResponseContent.cs index 4fd17b1b3..6f32d022f 100644 --- a/src/Auth0.ManagementApi/Types/UpdateClientGrantResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/UpdateClientGrantResponseContent.cs @@ -50,6 +50,10 @@ public record UpdateClientGrantResponseContent : IJsonOnDeserialized [JsonPropertyName("allow_any_organization")] public bool? AllowAnyOrganization { get; set; } + [Optional] + [JsonPropertyName("default_for")] + public ClientGrantDefaultForEnum? DefaultFor { get; set; } + /// /// If enabled, this grant is a special grant created by Auth0. It cannot be modified or deleted directly. /// diff --git a/src/Auth0.ManagementApi/Types/UpdateClientResponseContent.cs b/src/Auth0.ManagementApi/Types/UpdateClientResponseContent.cs index 1a2a25d70..56a129334 100644 --- a/src/Auth0.ManagementApi/Types/UpdateClientResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/UpdateClientResponseContent.cs @@ -309,6 +309,18 @@ public record UpdateClientResponseContent : IJsonOnDeserialized, IJsonOnSerializ [JsonPropertyName("express_configuration")] public ExpressConfiguration? ExpressConfiguration { get; set; } + [Optional] + [JsonPropertyName("my_organization_configuration")] + public ClientMyOrganizationResponseConfiguration? MyOrganizationConfiguration { get; set; } + + [Optional] + [JsonPropertyName("third_party_security_mode")] + public ClientThirdPartySecurityModeEnum? ThirdPartySecurityMode { get; set; } + + [Optional] + [JsonPropertyName("redirection_policy")] + public ClientRedirectionPolicyEnum? RedirectionPolicy { get; set; } + /// /// The identifier of the resource server that this client is linked to. /// diff --git a/src/Auth0.ManagementApi/Types/UpdateConnectionOptions.cs b/src/Auth0.ManagementApi/Types/UpdateConnectionOptions.cs index 6867f8988..b89e56482 100644 --- a/src/Auth0.ManagementApi/Types/UpdateConnectionOptions.cs +++ b/src/Auth0.ManagementApi/Types/UpdateConnectionOptions.cs @@ -99,6 +99,10 @@ public record UpdateConnectionOptions : IJsonOnDeserialized, IJsonOnSerializing [JsonPropertyName("api_enable_users")] public bool? ApiEnableUsers { get; set; } + [Optional] + [JsonPropertyName("api_enable_groups")] + public bool? ApiEnableGroups { get; set; } + [Optional] [JsonPropertyName("basic_profile")] public bool? BasicProfile { get; set; } diff --git a/src/Auth0.ManagementApi/Types/UpdateTenantSettingsResponseContent.cs b/src/Auth0.ManagementApi/Types/UpdateTenantSettingsResponseContent.cs index 3386854b5..a5125a533 100644 --- a/src/Auth0.ManagementApi/Types/UpdateTenantSettingsResponseContent.cs +++ b/src/Auth0.ManagementApi/Types/UpdateTenantSettingsResponseContent.cs @@ -211,6 +211,13 @@ public record UpdateTenantSettingsResponseContent : IJsonOnDeserialized [JsonPropertyName("resource_parameter_profile")] public TenantSettingsResourceParameterProfile? ResourceParameterProfile { get; set; } + /// + /// Whether the authorization server supports retrieving client metadata from a client_id URL. + /// + [Optional] + [JsonPropertyName("client_id_metadata_document_supported")] + public bool? ClientIdMetadataDocumentSupported { get; set; } + /// /// Whether Phone Consolidated Experience is enabled for this tenant. /// @@ -225,6 +232,10 @@ public record UpdateTenantSettingsResponseContent : IJsonOnDeserialized [JsonPropertyName("enable_ai_guide")] public bool? EnableAiGuide { get; set; } + [Optional] + [JsonPropertyName("dynamic_client_registration_security_mode")] + public TenantSettingsDynamicClientRegistrationSecurityMode? DynamicClientRegistrationSecurityMode { get; set; } + [JsonIgnore] public ReadOnlyAdditionalProperties AdditionalProperties { get; private set; } = new(); diff --git a/src/Auth0.ManagementApi/Wrapper/ManagementClient.cs b/src/Auth0.ManagementApi/Wrapper/ManagementClient.cs index e33883928..30d1662da 100644 --- a/src/Auth0.ManagementApi/Wrapper/ManagementClient.cs +++ b/src/Auth0.ManagementApi/Wrapper/ManagementClient.cs @@ -1,3 +1,5 @@ +using Auth0.ManagementApi.Core; + namespace Auth0.ManagementApi; /// @@ -65,12 +67,21 @@ private static ManagementClientOptions Validate(ManagementClientOptions options) return options; } + private static HttpClient CreateHttpClient(ManagementClientOptions options) => + options.CustomDomain != null + ? new HttpClient(new CustomDomainInterceptor()) + : new HttpClient(); + private static ClientOptions BuildClientOptions(ManagementClientOptions options) { + // When a custom domain is configured and no HttpClient is supplied, automatically + // inject CustomDomainInterceptor so the header is stripped from non-whitelisted paths. + var httpClient = options.HttpClient ?? CreateHttpClient(options); + var clientOptions = new ClientOptions { BaseUrl = $"https://{options.Domain}/api/v2", - HttpClient = options.HttpClient ?? new HttpClient(), + HttpClient = httpClient, Timeout = options.Timeout ?? TimeSpan.FromSeconds(30), MaxRetries = options.MaxRetries ?? 2, }; @@ -83,6 +94,9 @@ private static ClientOptions BuildClientOptions(ManagementClientOptions options) } } + if (!string.IsNullOrEmpty(options.CustomDomain)) + clientOptions.Headers[CustomDomainInterceptor.HeaderName] = options.CustomDomain; + return clientOptions; } diff --git a/src/Auth0.ManagementApi/Wrapper/ManagementClientOptions.cs b/src/Auth0.ManagementApi/Wrapper/ManagementClientOptions.cs index a794ea71c..57cba72e6 100644 --- a/src/Auth0.ManagementApi/Wrapper/ManagementClientOptions.cs +++ b/src/Auth0.ManagementApi/Wrapper/ManagementClientOptions.cs @@ -43,4 +43,18 @@ public class ManagementClientOptions /// Additional headers to include with every request. /// public IDictionary? AdditionalHeaders { get; init; } + + /// + /// Custom domain to include as the Auth0-Custom-Domain header on Management API + /// endpoints that generate user-facing links (email verification, password reset, + /// invitations, MFA enrollment tickets, etc.). + /// + /// + /// When set and no is provided, a + /// is automatically configured to strip the header from non-applicable endpoints. + /// When a custom is supplied, the header is still included on + /// every request but stripping is the caller's responsibility. + /// + /// + public string? CustomDomain { get; init; } } diff --git a/tests/Auth0.ManagementApi.Test/Core/CustomDomainInterceptorTest.cs b/tests/Auth0.ManagementApi.Test/Core/CustomDomainInterceptorTest.cs new file mode 100644 index 000000000..ca62e3109 --- /dev/null +++ b/tests/Auth0.ManagementApi.Test/Core/CustomDomainInterceptorTest.cs @@ -0,0 +1,185 @@ +using Auth0.ManagementApi.Core; +using NUnit.Framework; + +namespace Auth0.ManagementApi.Test.Core; + +[TestFixture] +public class CustomDomainInterceptorTest +{ + [Test] + [TestCase("/tickets/email-verification")] + [TestCase("/api/v2/tickets/email-verification")] + public void IsWhitelisted_EmailVerificationTicket_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/tickets/password-change")] + [TestCase("/api/v2/tickets/password-change")] + public void IsWhitelisted_PasswordChangeTicket_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/organizations/org_abc123/invitations")] + [TestCase("/api/v2/organizations/org_abc123/invitations")] + [TestCase("/organizations/org_abc123/invitations/inv_xyz789")] + [TestCase("/api/v2/organizations/org_abc123/invitations/inv_xyz789")] + public void IsWhitelisted_OrganizationInvitations_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/guardian/enrollments/ticket")] + [TestCase("/api/v2/guardian/enrollments/ticket")] + public void IsWhitelisted_GuardianEnrollmentTicket_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/jobs/verification-email")] + [TestCase("/api/v2/jobs/verification-email")] + public void IsWhitelisted_VerificationEmailJob_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/jobs/users-imports")] + [TestCase("/api/v2/jobs/users-imports")] + public void IsWhitelisted_UsersImportsJob_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/users")] + [TestCase("/api/v2/users")] + [TestCase("/users/auth0|abc123")] + [TestCase("/api/v2/users/auth0|abc123")] + public void IsWhitelisted_Users_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/self-service-profiles/ssp_1/sso-ticket")] + [TestCase("/api/v2/self-service-profiles/ssp_1/sso-ticket")] + [TestCase("/self-service-profiles/ssp_1/sso-ticket/t_1/revoke")] + [TestCase("/api/v2/self-service-profiles/ssp_1/sso-ticket/t_1/revoke")] + public void IsWhitelisted_SelfServiceProfileSsoTicket_ReturnsTrue(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.True); + + [Test] + [TestCase("/clients")] + [TestCase("/api/v2/clients")] + [TestCase("/clients/client_123")] + [TestCase("/connections")] + [TestCase("/api/v2/connections/conn_abc/status")] + [TestCase("/roles")] + [TestCase("/logs")] + [TestCase("/stats/active-users")] + [TestCase("/api/v2/organizations/org_abc123/members")] + [TestCase("/api/v2/organizations/org_abc123/connections")] + [TestCase("/jobs/users-exports")] + [TestCase("/api/v2/jobs/abc123")] + [TestCase("/guardian/enrollments")] + [TestCase("/api/v2/guardian/factors")] + [TestCase("/api/v2/users/auth0|abc123/roles")] + [TestCase("/api/v2/users/auth0|abc123/permissions")] + [TestCase("/users-by-email")] + [TestCase("/api/v2/users-by-email")] + public void IsWhitelisted_NonWhitelistedPath_ReturnsFalse(string path) => + Assert.That(CustomDomainInterceptor.IsWhitelisted(path), Is.False); + + [Test] + public void IsWhitelisted_NullPath_ReturnsFalse() => + Assert.That(CustomDomainInterceptor.IsWhitelisted(null), Is.False); + + [Test] + public void IsWhitelisted_EmptyPath_ReturnsFalse() => + Assert.That(CustomDomainInterceptor.IsWhitelisted(string.Empty), Is.False); + + [Test] + public async Task SendAsync_NonWhitelistedPath_StripsHeader() + { + var testHandler = new TestHandler(); + var interceptor = new CustomDomainInterceptor(testHandler); + var httpClient = new HttpClient(interceptor); + + var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/clients"); + request.Headers.Add(CustomDomainInterceptor.HeaderName, "login.mycompany.com"); + + await httpClient.SendAsync(request); + + Assert.That(testHandler.LastRequest!.Headers.Contains(CustomDomainInterceptor.HeaderName), Is.False); + } + + [Test] + public async Task SendAsync_WhitelistedPath_PreservesHeader() + { + var testHandler = new TestHandler(); + var interceptor = new CustomDomainInterceptor(testHandler); + var httpClient = new HttpClient(interceptor); + + var request = new HttpRequestMessage(HttpMethod.Post, + "http://localhost/tickets/email-verification"); + request.Headers.Add(CustomDomainInterceptor.HeaderName, "login.mycompany.com"); + + await httpClient.SendAsync(request); + + Assert.That(testHandler.LastRequest!.Headers.Contains(CustomDomainInterceptor.HeaderName), Is.True); + Assert.That( + testHandler.LastRequest.Headers.GetValues(CustomDomainInterceptor.HeaderName).First(), + Is.EqualTo("login.mycompany.com")); + } + + [Test] + public async Task SendAsync_NoHeader_DoesNotAddHeader() + { + var testHandler = new TestHandler(); + var interceptor = new CustomDomainInterceptor(testHandler); + var httpClient = new HttpClient(interceptor); + + var request = new HttpRequestMessage(HttpMethod.Post, + "http://localhost/tickets/email-verification"); + + await httpClient.SendAsync(request); + + Assert.That(testHandler.LastRequest!.Headers.Contains(CustomDomainInterceptor.HeaderName), Is.False); + } + + [Test] + public async Task SendAsync_NonWhitelistedPath_OnlyStripsCustomDomainHeader_LeavesOtherHeadersIntact() + { + // Verifies the interceptor is surgical: it removes only Auth0-Custom-Domain and does + // not disturb any other headers present on the same request. + var testHandler = new TestHandler(); + var interceptor = new CustomDomainInterceptor(testHandler); + var httpClient = new HttpClient(interceptor); + + var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/clients"); + request.Headers.Add(CustomDomainInterceptor.HeaderName, "login.mycompany.com"); + request.Headers.Add("X-Correlation-Id", "abc-123"); + request.Headers.Add("X-Custom-Header", "custom-value"); + + await httpClient.SendAsync(request); + + Assert.That(testHandler.LastRequest!.Headers.Contains(CustomDomainInterceptor.HeaderName), + Is.False, "Auth0-Custom-Domain should be stripped"); + Assert.That(testHandler.LastRequest.Headers.Contains("X-Correlation-Id"), + Is.True, "X-Correlation-Id should be preserved"); + Assert.That(testHandler.LastRequest.Headers.GetValues("X-Correlation-Id").First(), + Is.EqualTo("abc-123")); + Assert.That(testHandler.LastRequest.Headers.Contains("X-Custom-Header"), + Is.True, "X-Custom-Header should be preserved"); + Assert.That(testHandler.LastRequest.Headers.GetValues("X-Custom-Header").First(), + Is.EqualTo("custom-value")); + } + + /// + /// Helper handler to capture the outgoing request after passing through the interceptor for assertion. + /// + private sealed class TestHandler : HttpMessageHandler + { + public HttpRequestMessage? LastRequest { get; private set; } + + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + LastRequest = request; + return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)); + } + } +} diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/CreateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/CreateTest.cs index 45104b097..de0eb3528 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/CreateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/CreateTest.cs @@ -28,6 +28,7 @@ public async Task MockServerTest() ], "organization_usage": "deny", "allow_any_organization": true, + "default_for": "third_party_clients", "is_system": true, "subject_type": "client", "authorization_details_types": [ diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/GetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/GetTest.cs index 40dd9de80..65e43a9cb 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/GetTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/GetTest.cs @@ -21,6 +21,7 @@ public async Task MockServerTest() ], "organization_usage": "deny", "allow_any_organization": true, + "default_for": "third_party_clients", "is_system": true, "subject_type": "client", "authorization_details_types": [ diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/ListTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/ListTest.cs index b2e1fcfb5..cdec43ff4 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/ListTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/ListTest.cs @@ -24,6 +24,7 @@ public async Task MockServerTest() ], "organization_usage": "deny", "allow_any_organization": true, + "default_for": "third_party_clients", "is_system": true, "subject_type": "client", "authorization_details_types": [ @@ -45,6 +46,7 @@ public async Task MockServerTest() .WithParam("audience", "audience") .WithParam("client_id", "client_id") .WithParam("subject_type", "client") + .WithParam("default_for", "third_party_clients") .UsingGet() ) .RespondWith( @@ -63,6 +65,7 @@ public async Task MockServerTest() ClientId = "client_id", AllowAnyOrganization = true, SubjectType = ClientGrantSubjectTypeEnum.Client, + DefaultFor = ClientGrantDefaultForEnum.ThirdPartyClients, } ); await foreach (var item in items) diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/UpdateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/UpdateTest.cs index 76710fb19..5b8f68725 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/UpdateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/ClientGrants/UpdateTest.cs @@ -26,6 +26,7 @@ public async Task MockServerTest() ], "organization_usage": "deny", "allow_any_organization": true, + "default_for": "third_party_clients", "is_system": true, "subject_type": "client", "authorization_details_types": [ diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/CreateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/CreateTest.cs index 77bedacf5..1deceeb94 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/CreateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/CreateTest.cs @@ -56,7 +56,11 @@ public async Task MockServerTest() ], "enforce_device_binding": "ip", "allow_refresh_token": true, - "enforce_online_refresh_tokens": true + "enforce_online_refresh_tokens": true, + "delegation": { + "allow_delegated_access": true, + "enforce_device_binding": "ip" + } }, "oidc_logout": { "backchannel_logout_urls": [ @@ -363,6 +367,16 @@ public async Task MockServerTest() "admin_login_domain": "admin_login_domain", "oin_submission_id": "oin_submission_id" }, + "my_organization_configuration": { + "connection_profile_id": "connection_profile_id", + "user_attribute_profile_id": "user_attribute_profile_id", + "allowed_strategies": [ + "pingfederate" + ], + "connection_deletion_behavior": "allow" + }, + "third_party_security_mode": "strict", + "redirection_policy": "allow_always", "resource_server_identifier": "resource_server_identifier", "async_approval_notification_channels": [ "guardian-push" diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/GetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/GetTest.cs index 8888e5a47..2e4772fde 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/GetTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/GetTest.cs @@ -50,7 +50,11 @@ public async Task MockServerTest() ], "enforce_device_binding": "ip", "allow_refresh_token": true, - "enforce_online_refresh_tokens": true + "enforce_online_refresh_tokens": true, + "delegation": { + "allow_delegated_access": true, + "enforce_device_binding": "ip" + } }, "oidc_logout": { "backchannel_logout_urls": [ @@ -357,6 +361,16 @@ public async Task MockServerTest() "admin_login_domain": "admin_login_domain", "oin_submission_id": "oin_submission_id" }, + "my_organization_configuration": { + "connection_profile_id": "connection_profile_id", + "user_attribute_profile_id": "user_attribute_profile_id", + "allowed_strategies": [ + "pingfederate" + ], + "connection_deletion_behavior": "allow" + }, + "third_party_security_mode": "strict", + "redirection_policy": "allow_always", "resource_server_identifier": "resource_server_identifier", "async_approval_notification_channels": [ "guardian-push" diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/ListTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/ListTest.cs index 145a99e22..e6821c793 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/ListTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/ListTest.cs @@ -98,6 +98,14 @@ public async Task MockServerTest() "okta_oin_client_id": "okta_oin_client_id", "admin_login_domain": "admin_login_domain" }, + "my_organization_configuration": { + "allowed_strategies": [ + "pingfederate" + ], + "connection_deletion_behavior": "allow" + }, + "third_party_security_mode": "strict", + "redirection_policy": "allow_always", "resource_server_identifier": "resource_server_identifier", "async_approval_notification_channels": [ "guardian-push" diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/RotateSecretTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/RotateSecretTest.cs index 8204935ab..ef5b95d8f 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/RotateSecretTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/RotateSecretTest.cs @@ -49,7 +49,11 @@ public async Task MockServerTest() ], "enforce_device_binding": "ip", "allow_refresh_token": true, - "enforce_online_refresh_tokens": true + "enforce_online_refresh_tokens": true, + "delegation": { + "allow_delegated_access": true, + "enforce_device_binding": "ip" + } }, "oidc_logout": { "backchannel_logout_urls": [ @@ -356,6 +360,16 @@ public async Task MockServerTest() "admin_login_domain": "admin_login_domain", "oin_submission_id": "oin_submission_id" }, + "my_organization_configuration": { + "connection_profile_id": "connection_profile_id", + "user_attribute_profile_id": "user_attribute_profile_id", + "allowed_strategies": [ + "pingfederate" + ], + "connection_deletion_behavior": "allow" + }, + "third_party_security_mode": "strict", + "redirection_policy": "allow_always", "resource_server_identifier": "resource_server_identifier", "async_approval_notification_channels": [ "guardian-push" diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/UpdateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/UpdateTest.cs index 89adfe13c..41afb43b5 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/UpdateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Clients/UpdateTest.cs @@ -54,7 +54,11 @@ public async Task MockServerTest() ], "enforce_device_binding": "ip", "allow_refresh_token": true, - "enforce_online_refresh_tokens": true + "enforce_online_refresh_tokens": true, + "delegation": { + "allow_delegated_access": true, + "enforce_device_binding": "ip" + } }, "oidc_logout": { "backchannel_logout_urls": [ @@ -361,6 +365,16 @@ public async Task MockServerTest() "admin_login_domain": "admin_login_domain", "oin_submission_id": "oin_submission_id" }, + "my_organization_configuration": { + "connection_profile_id": "connection_profile_id", + "user_attribute_profile_id": "user_attribute_profile_id", + "allowed_strategies": [ + "pingfederate" + ], + "connection_deletion_behavior": "allow" + }, + "third_party_security_mode": "strict", + "redirection_policy": "allow_always", "resource_server_identifier": "resource_server_identifier", "async_approval_notification_channels": [ "guardian-push" diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/ListSynchronizedGroupsTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/ListSynchronizedGroupsTest.cs new file mode 100644 index 000000000..cbeac7d84 --- /dev/null +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/ListSynchronizedGroupsTest.cs @@ -0,0 +1,51 @@ +using Auth0.ManagementApi.Connections; +using Auth0.ManagementApi.Test.Unit.MockServer; +using NUnit.Framework; + +namespace Auth0.ManagementApi.Test.Unit.MockServer.Connections.DirectoryProvisioning; + +[TestFixture] +[Parallelizable(ParallelScope.Self)] +public class ListSynchronizedGroupsTest : BaseMockServerTest +{ + [NUnit.Framework.Test] + public async Task MockServerTest() + { + const string mockResponse = """ + { + "groups": [ + { + "id": "id" + } + ], + "next": "next" + } + """; + + Server + .Given( + WireMock + .RequestBuilders.Request.Create() + .WithPath("/connections/id/directory-provisioning/synchronized-groups") + .WithParam("from", "from") + .WithParam("take", "1") + .UsingGet() + ) + .RespondWith( + WireMock + .ResponseBuilders.Response.Create() + .WithStatusCode(200) + .WithBody(mockResponse) + ); + + var items = await Client.Connections.DirectoryProvisioning.ListSynchronizedGroupsAsync( + "id", + new ListSynchronizedGroupsRequestParameters { From = "from", Take = 1 } + ); + await foreach (var item in items) + { + Assert.That(item, Is.Not.Null); + break; // Only check the first item + } + } +} diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/SetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/SetTest.cs new file mode 100644 index 000000000..b25439650 --- /dev/null +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Connections/DirectoryProvisioning/SetTest.cs @@ -0,0 +1,49 @@ +using Auth0.ManagementApi; +using Auth0.ManagementApi.Connections; +using Auth0.ManagementApi.Test.Unit.MockServer; +using NUnit.Framework; + +namespace Auth0.ManagementApi.Test.Unit.MockServer.Connections.DirectoryProvisioning; + +[TestFixture] +[Parallelizable(ParallelScope.Self)] +public class SetTest : BaseMockServerTest +{ + [NUnit.Framework.Test] + public void MockServerTest() + { + const string requestJson = """ + { + "groups": [ + { + "id": "id" + } + ] + } + """; + + Server + .Given( + WireMock + .RequestBuilders.Request.Create() + .WithPath("/connections/id/directory-provisioning/synchronized-groups") + .WithHeader("Content-Type", "application/json") + .UsingPut() + .WithBodyAsJson(requestJson) + ) + .RespondWith(WireMock.ResponseBuilders.Response.Create().WithStatusCode(200)); + + Assert.DoesNotThrowAsync(async () => + await Client.Connections.DirectoryProvisioning.SetAsync( + "id", + new ReplaceSynchronizedGroupsRequestContent + { + Groups = new List() + { + new SynchronizedGroupPayload { Id = "id" }, + }, + } + ) + ); + } +} diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/CustomDomainHeaderTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/CustomDomainHeaderTest.cs new file mode 100644 index 000000000..f2c05c8e7 --- /dev/null +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/CustomDomainHeaderTest.cs @@ -0,0 +1,251 @@ +using Auth0.ManagementApi.Core; +using NUnit.Framework; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.Settings; +using WireMock.Logging; + +namespace Auth0.ManagementApi.Test.Unit.MockServer; + +/// +/// End-to-end tests for the Auth0-Custom-Domain header feature using WireMock as the HTTP backend. +/// +[TestFixture] +public class CustomDomainHeaderTest +{ + private WireMockServer _server = null!; + + [OneTimeSetUp] + public void GlobalSetup() + { + _server = WireMockServer.Start( + new WireMockServerSettings { Logger = new WireMockConsoleLogger() }); + } + + [OneTimeTearDown] + public void GlobalTeardown() + { + _server.Stop(); + _server.Dispose(); + } + + [SetUp] + public void Setup() => _server.Reset(); + + private ManagementApiClient BuildClient(string? customDomain = null, bool withInterceptor = false) + { + var httpClient = withInterceptor + ? new HttpClient(new CustomDomainInterceptor(new HttpClientHandler())) + : new HttpClient(); + + return new ManagementApiClient( + "TOKEN", + new ClientOptions + { + BaseUrl = _server.Urls[0], + MaxRetries = 0, + CustomDomain = customDomain, + HttpClient = httpClient, + }); + } + + private void StubAny(string path, string method = "GET") => + _server + .Given(Request.Create().WithPath(path).UsingMethod(method)) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("{}")); + + private bool HasCustomDomainHeader(string domain) => + _server.LogEntries.Any(e => + e.RequestMessage.Headers.ContainsKey(CustomDomainInterceptor.HeaderName) && + e.RequestMessage.Headers[CustomDomainInterceptor.HeaderName] + .Contains(domain, StringComparer.OrdinalIgnoreCase)); + + private bool HasNoCustomDomainHeader() => + _server.LogEntries.All(e => + !e.RequestMessage.Headers.ContainsKey(CustomDomainInterceptor.HeaderName)); + + [Test] + public async Task GlobalConfig_WhitelistedEndpoint_HeaderPresent() + { + StubAny("/tickets/email-verification", "POST"); + var client = BuildClient(customDomain: "login.mycompany.com"); + + try + { + await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|123" }); + } + catch { /* ignore deserialization of empty body */ } + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasCustomDomainHeader("login.mycompany.com"), Is.True); + } + + [Test] + public async Task GlobalConfig_NoInterceptor_NonWhitelistedEndpoint_HeaderStillSent() + { + // Without the interceptor, the header is present on ALL requests (including non-whitelisted). + // Servers ignore unknown headers, so this is acceptable. Document the behaviour here. + StubAny("/connections/conn_1/status"); + var client = BuildClient(customDomain: "login.mycompany.com"); + + await client.Connections.CheckStatusAsync("conn_1"); + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasCustomDomainHeader("login.mycompany.com"), Is.True, + "Without CustomDomainInterceptor the header is present on all requests."); + } + + [Test] + public async Task GlobalConfig_WithInterceptor_WhitelistedEndpoint_HeaderPresent() + { + StubAny("/tickets/email-verification", "POST"); + var client = BuildClient(customDomain: "login.mycompany.com", withInterceptor: true); + + try + { + await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|123" }); + } + catch { /* ignore deserialization of empty body */ } + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasCustomDomainHeader("login.mycompany.com"), Is.True); + } + + [Test] + public async Task GlobalConfig_WithInterceptor_NonWhitelistedEndpoint_HeaderStripped() + { + StubAny("/connections/conn_1/status"); + var client = BuildClient(customDomain: "login.mycompany.com", withInterceptor: true); + + await client.Connections.CheckStatusAsync("conn_1"); + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasNoCustomDomainHeader(), Is.True, + "CustomDomainInterceptor should strip the header from non-whitelisted paths."); + } + + [Test] + public async Task PerRequest_WhitelistedEndpoint_HeaderPresent() + { + StubAny("/tickets/email-verification", "POST"); + var client = BuildClient(); // no global custom domain + + try + { + await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|123" }, + CustomDomainHeader.For("login.mycompany.com")); + } + catch { /* ignore deserialization of empty body */ } + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasCustomDomainHeader("login.mycompany.com"), Is.True); + } + + [Test] + public async Task PerRequest_OverridesGlobalDomain() + { + StubAny("/tickets/email-verification", "POST"); + var client = BuildClient(customDomain: "global.mycompany.com"); + + try + { + await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|123" }, + CustomDomainHeader.For("override.mycompany.com")); + } + catch { /* ignore deserialization of empty body */ } + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + // The per-request value should appear (AdditionalHeaders override Options.Headers) + Assert.That(HasCustomDomainHeader("override.mycompany.com"), Is.True); + } + + [Test] + public async Task NoCustomDomain_HeaderAbsent() + { + StubAny("/connections/conn_1/status"); + var client = BuildClient(); // no custom domain + + await client.Connections.CheckStatusAsync("conn_1"); + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + Assert.That(HasNoCustomDomainHeader(), Is.True); + } + + [Test] + public async Task PerRequest_WithOtherAdditionalHeaders_AllHeadersPresent() + { + // Users who need custom domain AND other per-request headers construct RequestOptions + // directly rather than using CustomDomainHeader.For(), which only sets the custom domain. + StubAny("/tickets/email-verification", "POST"); + var client = BuildClient(); + + try + { + await client.Tickets.VerifyEmailAsync( + new VerifyEmailTicketRequestContent { UserId = "auth0|123" }, + new RequestOptions + { + AdditionalHeaders = new[] + { + new KeyValuePair( + CustomDomainInterceptor.HeaderName, "login.mycompany.com"), + new KeyValuePair( + "X-Correlation-Id", "test-correlation-id"), + }, + }); + } + catch { /* ignore deserialization of empty body */ } + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + + var headers = _server.LogEntries[0].RequestMessage.Headers; + + Assert.That(HasCustomDomainHeader("login.mycompany.com"), Is.True, + "Auth0-Custom-Domain header should be present"); + Assert.That(headers.ContainsKey("X-Correlation-Id"), Is.True, + "X-Correlation-Id should be present alongside Auth0-Custom-Domain"); + Assert.That(headers["X-Correlation-Id"].First(), Is.EqualTo("test-correlation-id")); + } + + [Test] + public async Task GlobalConfig_WithInterceptor_NonWhitelistedEndpoint_OtherHeadersPreserved() + { + // The interceptor must only strip Auth0-Custom-Domain; it must not affect other + // custom headers the caller has added to the request. + _server + .Given(Request.Create().WithPath("/connections/conn_1/status").UsingGet()) + .RespondWith(Response.Create().WithStatusCode(200).WithBody("{}")); + + var httpClient = new HttpClient(new CustomDomainInterceptor(new HttpClientHandler())); + var client = new ManagementApiClient( + "TOKEN", + new ClientOptions + { + BaseUrl = _server.Urls[0], + MaxRetries = 0, + CustomDomain = "login.mycompany.com", + HttpClient = httpClient, + AdditionalHeaders = new[] + { + new KeyValuePair("X-Custom-Global", "global-value"), + }, + }); + + await client.Connections.CheckStatusAsync("conn_1"); + + Assert.That(_server.LogEntries, Has.Count.GreaterThan(0)); + + var headers = _server.LogEntries[0].RequestMessage.Headers; + + Assert.That(headers.ContainsKey(CustomDomainInterceptor.HeaderName), Is.False, + "Auth0-Custom-Domain should be stripped from non-whitelisted endpoint"); + Assert.That(headers.ContainsKey("X-Custom-Global"), Is.True, + "Other custom headers must not be removed by the interceptor"); + Assert.That(headers["X-Custom-Global"].First(), Is.EqualTo("global-value")); + } +} diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/GetHistoryTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/GetHistoryTest.cs index 4a6848380..0c8f09507 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/GetHistoryTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/GetHistoryTest.cs @@ -16,7 +16,7 @@ public async Task MockServerTest() "id": "id", "event_stream_id": "event_stream_id", "status": "failed", - "event_type": "user.created", + "event_type": "group.created", "attempts": [ { "status": "failed", diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/ListTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/ListTest.cs index 9d3c5e671..9beefa699 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/ListTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Deliveries/ListTest.cs @@ -18,7 +18,7 @@ public async Task MockServerTest() "id": "id", "event_stream_id": "event_stream_id", "status": "failed", - "event_type": "user.created", + "event_type": "group.created", "attempts": [ { "status": "failed", diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Redeliveries/CreateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Redeliveries/CreateTest.cs index 5613fa0ea..6c4fe628e 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Redeliveries/CreateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/Redeliveries/CreateTest.cs @@ -24,7 +24,7 @@ public async Task MockServerTest() "failed" ], "event_types": [ - "user.created" + "group.created" ] } """; diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/TestTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/TestTest.cs index 124abc8cb..405183961 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/TestTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/EventStreams/TestTest.cs @@ -14,7 +14,7 @@ public async Task MockServerTest() { const string requestJson = """ { - "event_type": "user.created" + "event_type": "group.created" } """; @@ -23,7 +23,7 @@ public async Task MockServerTest() "id": "id", "event_stream_id": "event_stream_id", "status": "failed", - "event_type": "user.created", + "event_type": "group.created", "attempts": [ { "status": "failed", @@ -62,7 +62,7 @@ public async Task MockServerTest() "id", new CreateEventStreamTestEventRequestContent { - EventType = EventStreamTestEventTypeEnum.UserCreated, + EventType = EventStreamTestEventTypeEnum.GroupCreated, } ); JsonAssert.AreEqual(response, mockResponse); diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/GetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/GetTest.cs index 79e2535b8..e2fe733a0 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/GetTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/GetTest.cs @@ -29,9 +29,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], @@ -67,9 +64,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/SetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/SetTest.cs index 858ddda38..468934281 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/SetTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/SetTest.cs @@ -41,9 +41,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], @@ -79,9 +76,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/UpdateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/UpdateTest.cs index 3b87fc6ae..0838c2c7d 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/UpdateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/NetworkAcls/UpdateTest.cs @@ -34,9 +34,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], @@ -72,9 +69,6 @@ public async Task MockServerTest() "asns": [ 1 ], - "auth0_managed": [ - "auth0_managed" - ], "geo_country_codes": [ "geo_country_codes" ], diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/GetTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/GetTest.cs index ac12f5166..d5c49e9dc 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/GetTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/GetTest.cs @@ -113,8 +113,10 @@ public async Task MockServerTest() "authorization_response_iss_parameter_supported": true, "skip_non_verifiable_callback_uri_confirmation_prompt": true, "resource_parameter_profile": "audience", + "client_id_metadata_document_supported": true, "phone_consolidated_experience": true, - "enable_ai_guide": true + "enable_ai_guide": true, + "dynamic_client_registration_security_mode": "strict" } """; diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/UpdateTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/UpdateTest.cs index 0afb3b5b0..b426c9f26 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/UpdateTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Tenants/Settings/UpdateTest.cs @@ -117,8 +117,10 @@ public async Task MockServerTest() "authorization_response_iss_parameter_supported": true, "skip_non_verifiable_callback_uri_confirmation_prompt": true, "resource_parameter_profile": "audience", + "client_id_metadata_document_supported": true, "phone_consolidated_experience": true, - "enable_ai_guide": true + "enable_ai_guide": true, + "dynamic_client_registration_security_mode": "strict" } """; diff --git a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Users/ConnectedAccounts/ListTest.cs b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Users/ConnectedAccounts/ListTest.cs index 38c00efcc..00110bdd7 100644 --- a/tests/Auth0.ManagementApi.Test/Unit/MockServer/Users/ConnectedAccounts/ListTest.cs +++ b/tests/Auth0.ManagementApi.Test/Unit/MockServer/Users/ConnectedAccounts/ListTest.cs @@ -24,7 +24,8 @@ public async Task MockServerTest() "scopes" ], "created_at": "2024-01-15T09:30:00.000Z", - "expires_at": "2024-01-15T09:30:00.000Z" + "expires_at": "2024-01-15T09:30:00.000Z", + "organization_id": "organization_id" } ], "next": "next"