Skip to content

Commit c117f3c

Browse files
authored
[SDK-4542] Support organization in client credentials (#582)
1 parent b31f779 commit c117f3c

20 files changed

Lines changed: 934 additions & 15 deletions

src/main/java/com/auth0/client/auth/AuthAPI.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class AuthAPI {
6363
private static final String PATH_REVOKE = "revoke";
6464
private static final String PATH_PASSWORDLESS = "passwordless";
6565
private static final String PATH_START = "start";
66+
private static final String KEY_ORGANIZATION = "organization";
6667

6768
private final Auth0HttpClient client;
6869
private final String clientId;
@@ -715,12 +716,40 @@ public TokenRequest exchangePasswordlessOtp(String emailOrPhone, String realm, c
715716
* @return a Request to configure and execute.
716717
*/
717718
public TokenRequest requestToken(String audience) {
719+
return requestToken(audience, null);
720+
}
721+
722+
/**
723+
* Creates a request to get a Token for the given audience using the 'Client Credentials' grant.
724+
* Default used realm is defined in the "API Authorization Settings" in the account's advanced settings in the Auth0 Dashboard.
725+
* <strong>This operation requires that a client secret be configured for the {@code AuthAPI} client.</strong>
726+
* <pre>
727+
* {@code
728+
* try {
729+
* TokenHolder result = authAPI.requestToken("https://myapi.me.auth0.com/users", "org_123")
730+
* .execute()
731+
* .getBody();
732+
* } catch (Auth0Exception e) {
733+
* //Something happened
734+
* }
735+
* }
736+
* </pre>
737+
*
738+
* @see <a href="https://auth0.com/docs/api/authentication#client-credentials-flow">Client Credentials Flow API docs</a>
739+
* @param audience the audience of the API to request access to.
740+
* @param org the organization name or ID to be included in the request.
741+
* @return a Request to configure and execute.
742+
*/
743+
public TokenRequest requestToken(String audience, String org) {
718744
Asserts.assertNotNull(audience, "audience");
719745

720746
TokenRequest request = new TokenRequest(client, getTokenUrl());
721747
request.addParameter(KEY_CLIENT_ID, clientId);
722748
request.addParameter(KEY_GRANT_TYPE, "client_credentials");
723749
request.addParameter(KEY_AUDIENCE, audience);
750+
if (org != null && !org.trim().isEmpty()) {
751+
request.addParameter(KEY_ORGANIZATION, org);
752+
}
724753
addClientAuthentication(request, true);
725754
return request;
726755
}

src/main/java/com/auth0/client/mgmt/ClientGrantsEntity.java

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.auth0.client.mgmt;
22

33
import com.auth0.client.mgmt.filter.ClientGrantsFilter;
4+
import com.auth0.client.mgmt.filter.PageFilter;
45
import com.auth0.json.mgmt.clientgrants.ClientGrant;
56
import com.auth0.json.mgmt.clientgrants.ClientGrantsPage;
7+
import com.auth0.json.mgmt.organizations.OrganizationsPage;
68
import com.auth0.net.BaseRequest;
79
import com.auth0.net.Request;
810
import com.auth0.net.VoidRequest;
@@ -61,24 +63,44 @@ public Request<ClientGrantsPage> list(ClientGrantsFilter filter) {
6163
* @return a Request to execute.
6264
*/
6365
public Request<ClientGrant> create(String clientId, String audience, String[] scope) {
66+
return create(clientId, audience, scope, null, null);
67+
}
68+
69+
/**
70+
* Create a Client Grant. A token with scope create:client_grants is needed.
71+
* See https://auth0.com/docs/api/management/v2#!/Client_Grants/post_client_grants
72+
*
73+
* @param clientId the application's client id to associate this grant with.
74+
* @param audience the audience of the grant.
75+
* @param scope the scope to grant.
76+
* @param orgUsage Defines whether organizations can be used with client credentials exchanges for this grant. (defaults to deny when not defined)
77+
* @param allowAnyOrg If true, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations.
78+
* @return a Request to execute.
79+
*/
80+
public Request<ClientGrant> create(String clientId, String audience, String[] scope, String orgUsage, Boolean allowAnyOrg) {
6481
Asserts.assertNotNull(clientId, "client id");
6582
Asserts.assertNotNull(audience, "audience");
6683
Asserts.assertNotNull(scope, "scope");
6784

6885
String url = baseUrl
69-
.newBuilder()
70-
.addPathSegments("api/v2/client-grants")
71-
.build()
72-
.toString();
86+
.newBuilder()
87+
.addPathSegments("api/v2/client-grants")
88+
.build()
89+
.toString();
7390
BaseRequest<ClientGrant> request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference<ClientGrant>() {
7491
});
7592
request.addParameter("client_id", clientId);
7693
request.addParameter("audience", audience);
7794
request.addParameter("scope", scope);
95+
if (orgUsage != null && !orgUsage.trim().isEmpty()) {
96+
request.addParameter("organization_usage", orgUsage);
97+
}
98+
if (allowAnyOrg != null) {
99+
request.addParameter("allow_any_organization", allowAnyOrg);
100+
}
78101
return request;
79102
}
80103

81-
82104
/**
83105
* Delete an existing Client Grant. A token with scope delete:client_grants is needed.
84106
* See https://auth0.com/docs/api/management/v2#!/Client_Grants/delete_client_grants_by_id
@@ -107,18 +129,63 @@ public Request<Void> delete(String clientGrantId) {
107129
* @return a Request to execute.
108130
*/
109131
public Request<ClientGrant> update(String clientGrantId, String[] scope) {
132+
return update(clientGrantId, scope, null, null);
133+
}
134+
135+
/**
136+
* Update an existing Client Grant. A token with scope update:client_grants is needed.
137+
* See https://auth0.com/docs/api/management/v2#!/Client_Grants/patch_client_grants_by_id
138+
*
139+
* @param clientGrantId the client grant id.
140+
* @param scope the scope to grant.
141+
* @param orgUsage Defines whether organizations can be used with client credentials exchanges for this grant. (defaults to deny when not defined)
142+
* @param allowAnyOrg If true, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations.
143+
* @return a Request to execute.
144+
*/
145+
public Request<ClientGrant> update(String clientGrantId, String[] scope, String orgUsage, Boolean allowAnyOrg) {
110146
Asserts.assertNotNull(clientGrantId, "client grant id");
111147
Asserts.assertNotNull(scope, "scope");
112148

113149
String url = baseUrl
114-
.newBuilder()
115-
.addPathSegments("api/v2/client-grants")
116-
.addPathSegment(clientGrantId)
117-
.build()
118-
.toString();
150+
.newBuilder()
151+
.addPathSegments("api/v2/client-grants")
152+
.addPathSegment(clientGrantId)
153+
.build()
154+
.toString();
119155
BaseRequest<ClientGrant> request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference<ClientGrant>() {
120156
});
121157
request.addParameter("scope", scope);
158+
if (orgUsage != null && !orgUsage.trim().isEmpty()) {
159+
request.addParameter("organization_usage", orgUsage);
160+
}
161+
if (allowAnyOrg != null) {
162+
request.addParameter("allow_any_organization", allowAnyOrg);
163+
}
122164
return request;
123165
}
166+
167+
/**
168+
* Returns the organizations associated with this client grant. A token with scope {@code read:organization_client_grants} is required.
169+
* @param clientGrantId the client grant ID.
170+
* @param filter an optional filter to limit results.
171+
* @return a request to execute.
172+
*/
173+
public Request<OrganizationsPage> listOrganizations(String clientGrantId, PageFilter filter) {
174+
Asserts.assertNotNull(clientGrantId, "client grant ID");
175+
HttpUrl.Builder builder = baseUrl
176+
.newBuilder()
177+
.addPathSegments("api/v2/client-grants")
178+
.addPathSegment(clientGrantId)
179+
.addPathSegment("organizations");
180+
181+
if (filter != null) {
182+
for (Map.Entry<String, Object> e : filter.getAsMap().entrySet()) {
183+
builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue()));
184+
}
185+
}
186+
187+
String url = builder.build().toString();
188+
return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference<OrganizationsPage>() {
189+
});
190+
}
124191
}

src/main/java/com/auth0/client/mgmt/OrganizationsEntity.java

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.auth0.client.mgmt;
22

3-
import com.auth0.client.mgmt.filter.BaseFilter;
4-
import com.auth0.client.mgmt.filter.FieldsFilter;
5-
import com.auth0.client.mgmt.filter.InvitationsFilter;
6-
import com.auth0.client.mgmt.filter.PageFilter;
3+
import com.auth0.client.mgmt.filter.*;
74
import com.auth0.json.mgmt.roles.RolesPage;
85
import com.auth0.json.mgmt.organizations.*;
96
import com.auth0.net.BaseRequest;
@@ -602,6 +599,73 @@ public Request<Void> deleteInvitation(String orgId, String invitationId) {
602599
return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE);
603600
}
604601

602+
/**
603+
* Get the client grants associated with this organization. A token with scope {@code read:organization_client_grants} is required.
604+
* @param orgId the organization ID.
605+
* @param filter an optional filter to refine results.
606+
* @return a request to execute.
607+
*/
608+
public Request<OrganizationClientGrantsPage> listClientGrants(String orgId, OrganizationClientGrantsFilter filter) {
609+
Asserts.assertNotNull(orgId, "organization ID");
610+
611+
HttpUrl.Builder builder = baseUrl
612+
.newBuilder()
613+
.addPathSegments(ORGS_PATH)
614+
.addPathSegments(orgId)
615+
.addPathSegment("client-grants");
616+
617+
applyFilter(filter, builder);
618+
619+
String url = builder.build().toString();
620+
621+
return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference<OrganizationClientGrantsPage>() {});
622+
}
623+
624+
/**
625+
* Associate a client grant with an organization. A token with scope {@code create:organization_client_grants} is required.
626+
* @param orgId the organization ID.
627+
* @param addOrganizationClientGrantRequestBody the body of the request containing information about the client grant to associate.
628+
* @return a request to execute.
629+
*/
630+
public Request<OrganizationClientGrant> addClientGrant(String orgId, CreateOrganizationClientGrantRequestBody addOrganizationClientGrantRequestBody) {
631+
Asserts.assertNotNull(orgId, "organization ID");
632+
Asserts.assertNotNull(addOrganizationClientGrantRequestBody, "client grant");
633+
634+
String url = baseUrl
635+
.newBuilder()
636+
.addPathSegments(ORGS_PATH)
637+
.addPathSegment(orgId)
638+
.addPathSegment("client-grants")
639+
.build()
640+
.toString();
641+
642+
BaseRequest<OrganizationClientGrant> request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference<OrganizationClientGrant>() {});
643+
request.setBody(addOrganizationClientGrantRequestBody);
644+
return request;
645+
}
646+
647+
/**
648+
* Remove a client grant from an organization. A token with scope {@code delete:organization_client_grants} is required.
649+
* @param orgId the organization ID.
650+
* @param grantId the client grant ID.
651+
* @return a request to execute.
652+
*/
653+
public Request<Void> deleteClientGrant(String orgId, String grantId) {
654+
Asserts.assertNotNull(orgId, "organization ID");
655+
Asserts.assertNotNull(grantId, "client grant ID");
656+
657+
String url = baseUrl
658+
.newBuilder()
659+
.addPathSegments(ORGS_PATH)
660+
.addPathSegment(orgId)
661+
.addPathSegment("client-grants")
662+
.addPathSegment(grantId)
663+
.build()
664+
.toString();
665+
666+
return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE);
667+
}
668+
605669
private void applyFilter(BaseFilter filter, HttpUrl.Builder builder) {
606670
if (filter != null) {
607671
for (Map.Entry<String, Object> e : filter.getAsMap().entrySet()) {

src/main/java/com/auth0/client/mgmt/filter/ClientGrantsFilter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ public ClientGrantsFilter withAudience(String audience) {
3131
return this;
3232
}
3333

34+
/**
35+
* Filter by {@code allow_any_organization}
36+
* @param allowAnyOrganization only retrieve items with the {@code allow_any_organization} value specfied.
37+
* @return this filter instance.
38+
*/
39+
public ClientGrantsFilter withAllowAnyOrganization(Boolean allowAnyOrganization) {
40+
parameters.put("allow_any_organization", allowAnyOrganization);
41+
return this;
42+
}
43+
3444
/**
3545
* Filter by page
3646
*
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.auth0.client.mgmt.filter;
2+
3+
/**
4+
* Class used to filter the results received when listing the client grants associated with an organization.
5+
* Related to the {@link com.auth0.client.mgmt.OrganizationsEntity} entity.
6+
*/
7+
public class OrganizationClientGrantsFilter extends BaseFilter {
8+
9+
/**
10+
* Filter by client id
11+
*
12+
* @param clientId only retrieve items with this client id.
13+
* @return this filter instance
14+
*/
15+
public OrganizationClientGrantsFilter withClientId(String clientId) {
16+
parameters.put("client_id", clientId);
17+
return this;
18+
}
19+
20+
/**
21+
* Filter by audience
22+
*
23+
* @param audience only retrieve the item with this audience.
24+
* @return this filter instance
25+
*/
26+
public OrganizationClientGrantsFilter withAudience(String audience) {
27+
parameters.put("audience", audience);
28+
return this;
29+
}
30+
31+
/**
32+
* Filter by page
33+
*
34+
* @param pageNumber the page number to retrieve.
35+
* @param amountPerPage the amount of items per page to retrieve.
36+
* @return this filter instance
37+
*/
38+
public OrganizationClientGrantsFilter withPage(int pageNumber, int amountPerPage) {
39+
parameters.put("page", pageNumber);
40+
parameters.put("per_page", amountPerPage);
41+
return this;
42+
}
43+
44+
/**
45+
* Include the query summary
46+
*
47+
* @param includeTotals whether to include or not the query summary.
48+
* @return this filter instance
49+
*/
50+
public OrganizationClientGrantsFilter withTotals(boolean includeTotals) {
51+
parameters.put("include_totals", includeTotals);
52+
return this;
53+
}
54+
}

src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrant.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public class ClientGrant {
2222
private String audience;
2323
@JsonProperty("scope")
2424
private List<String> scope;
25+
@JsonProperty("organization_usage")
26+
private String organizationUsage;
27+
@JsonProperty("allow_any_organization")
28+
private Boolean allowAnyOrganization;
2529

2630
/**
2731
* Getter for the id of the client grant.
@@ -92,4 +96,32 @@ public List<String> getScope() {
9296
public void setScope(List<String> scope) {
9397
this.scope = scope;
9498
}
99+
100+
/**
101+
* @return the organization use
102+
*/
103+
public String getOrganizationUsage() {
104+
return organizationUsage;
105+
}
106+
107+
/**
108+
* @param organizationUsage the value of {@code organization_usage} to set.
109+
*/
110+
public void setOrganizationUsage(String organizationUsage) {
111+
this.organizationUsage = organizationUsage;
112+
}
113+
114+
/**
115+
* @return the value of {@code allow_any_organization}
116+
*/
117+
public Boolean getAllowAnyOrganization() {
118+
return allowAnyOrganization;
119+
}
120+
121+
/**
122+
* @param allowAnyOrganization the value of {@code allow_any_organization} to set.
123+
*/
124+
public void setAllowAnyOrganization(Boolean allowAnyOrganization) {
125+
this.allowAnyOrganization = allowAnyOrganization;
126+
}
95127
}

0 commit comments

Comments
 (0)