Skip to content

Add operations to create and delete SAML provider configs. #420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 104 additions & 8 deletions src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -939,13 +939,15 @@ protected String execute() throws FirebaseAuthException {
}

/**
* Creates a new provider OIDC Auth config with the attributes contained in the specified {@link
* OidcProviderConfig.CreateRequest}.
* Creates a new OIDC Auth provider config with the attributes contained in the specified
* {@link OidcProviderConfig.CreateRequest}.
*
* @param request A non-null {@link OidcProviderConfig.CreateRequest} instance.
* @return An {@link OidcProviderConfig} instance corresponding to the newly created provider
* config.
* @throws NullPointerException if the provided request is null.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not
* prefixed with 'oidc.'.
* @throws FirebaseAuthException if an error occurs while creating the provider config.
*/
public OidcProviderConfig createOidcProviderConfig(
Expand All @@ -961,6 +963,8 @@ public OidcProviderConfig createOidcProviderConfig(
* instance corresponding to the newly created provider config. If an error occurs while
* creating the provider config, the future throws a {@link FirebaseAuthException}.
* @throws NullPointerException if the provided request is null.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not
* prefixed with 'oidc.'.
*/
public ApiFuture<OidcProviderConfig> createOidcProviderConfigAsync(
@NonNull OidcProviderConfig.CreateRequest request) {
Expand All @@ -971,6 +975,7 @@ public ApiFuture<OidcProviderConfig> createOidcProviderConfigAsync(
createOidcProviderConfigOp(final OidcProviderConfig.CreateRequest request) {
checkNotDestroyed();
checkNotNull(request, "Create request must not be null.");
OidcProviderConfig.checkOidcProviderId(request.getProviderId());
final FirebaseUserManager userManager = getUserManager();
return new CallableOperation<OidcProviderConfig, FirebaseAuthException>() {
@Override
Expand Down Expand Up @@ -1025,7 +1030,8 @@ protected OidcProviderConfig execute() throws FirebaseAuthException {
*
* @param providerId A provider ID string.
* @return An {@link OidcProviderConfig} instance.
* @throws IllegalArgumentException If the provider ID string is null or empty.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with 'oidc'.
* @throws FirebaseAuthException If an error occurs while retrieving the provider config.
*/
public OidcProviderConfig getOidcProviderConfig(@NonNull String providerId)
Expand All @@ -1042,7 +1048,8 @@ public OidcProviderConfig getOidcProviderConfig(@NonNull String providerId)
* {@link OidcProviderConfig} instance. If an error occurs while retrieving the provider
* config or if the specified provider ID does not exist, the future throws a
* {@link FirebaseAuthException}.
* @throws IllegalArgumentException If the provider ID string is null or empty.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not
* prefixed with 'oidc.'.
*/
public ApiFuture<OidcProviderConfig> getOidcProviderConfigAsync(@NonNull String providerId) {
return getOidcProviderConfigOp(providerId).callAsync(firebaseApp);
Expand All @@ -1051,7 +1058,7 @@ public ApiFuture<OidcProviderConfig> getOidcProviderConfigAsync(@NonNull String
private CallableOperation<OidcProviderConfig, FirebaseAuthException>
getOidcProviderConfigOp(final String providerId) {
checkNotDestroyed();
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
OidcProviderConfig.checkOidcProviderId(providerId);
final FirebaseUserManager userManager = getUserManager();
return new CallableOperation<OidcProviderConfig, FirebaseAuthException>() {
@Override
Expand Down Expand Up @@ -1152,7 +1159,8 @@ protected ListProviderConfigsPage<OidcProviderConfig> execute()
* Deletes the OIDC Auth provider config identified by the specified provider ID.
*
* @param providerId A provider ID string.
* @throws IllegalArgumentException If the provider ID string is null or empty.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with 'oidc'.
* @throws FirebaseAuthException If an error occurs while deleting the provider config.
*/
public void deleteOidcProviderConfig(@NonNull String providerId) throws FirebaseAuthException {
Expand All @@ -1166,7 +1174,8 @@ public void deleteOidcProviderConfig(@NonNull String providerId) throws Firebase
* @return An {@code ApiFuture} which will complete successfully when the specified provider
* config has been deleted. If an error occurs while deleting the provider config, the future
* throws a {@link FirebaseAuthException}.
* @throws IllegalArgumentException If the provider ID string is null or empty.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with "oidc.".
*/
public ApiFuture<Void> deleteOidcProviderConfigAsync(String providerId) {
return deleteOidcProviderConfigOp(providerId).callAsync(firebaseApp);
Expand All @@ -1175,7 +1184,7 @@ public ApiFuture<Void> deleteOidcProviderConfigAsync(String providerId) {
private CallableOperation<Void, FirebaseAuthException> deleteOidcProviderConfigOp(
final String providerId) {
checkNotDestroyed();
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
OidcProviderConfig.checkOidcProviderId(providerId);
final FirebaseUserManager userManager = getUserManager();
return new CallableOperation<Void, FirebaseAuthException>() {
@Override
Expand All @@ -1186,6 +1195,93 @@ protected Void execute() throws FirebaseAuthException {
};
}

/**
* Creates a new SAML Auth provider config with the attributes contained in the specified
* {@link SamlProviderConfig.CreateRequest}.
*
* @param request A non-null {@link SamlProviderConfig.CreateRequest} instance.
* @return An {@link SamlProviderConfig} instance corresponding to the newly created provider
* config.
* @throws NullPointerException if the provided request is null.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with 'saml'.
* @throws FirebaseAuthException if an error occurs while creating the provider config.
*/
public SamlProviderConfig createSamlProviderConfig(
@NonNull SamlProviderConfig.CreateRequest request) throws FirebaseAuthException {
return createSamlProviderConfigOp(request).call();
}

/**
* Similar to {@link #createSamlProviderConfig} but performs the operation asynchronously.
*
* @param request A non-null {@link SamlProviderConfig.CreateRequest} instance.
* @return An {@code ApiFuture} which will complete successfully with a {@link SamlProviderConfig}
* instance corresponding to the newly created provider config. If an error occurs while
* creating the provider config, the future throws a {@link FirebaseAuthException}.
* @throws NullPointerException if the provided request is null.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with 'saml'.
*/
public ApiFuture<SamlProviderConfig> createSamlProviderConfigAsync(
@NonNull SamlProviderConfig.CreateRequest request) {
return createSamlProviderConfigOp(request).callAsync(firebaseApp);
}

private CallableOperation<SamlProviderConfig, FirebaseAuthException>
createSamlProviderConfigOp(final SamlProviderConfig.CreateRequest request) {
checkNotDestroyed();
checkNotNull(request, "Create request must not be null.");
SamlProviderConfig.checkSamlProviderId(request.getProviderId());
final FirebaseUserManager userManager = getUserManager();
return new CallableOperation<SamlProviderConfig, FirebaseAuthException>() {
@Override
protected SamlProviderConfig execute() throws FirebaseAuthException {
return userManager.createSamlProviderConfig(request);
}
};
}

/**
* Deletes the SAML Auth provider config identified by the specified provider ID.
*
* @param providerId A provider ID string.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with "saml.".
* @throws FirebaseAuthException If an error occurs while deleting the provider config.
*/
public void deleteSamlProviderConfig(@NonNull String providerId) throws FirebaseAuthException {
deleteSamlProviderConfigOp(providerId).call();
}

/**
* Similar to {@link #deleteSamlProviderConfig} but performs the operation asynchronously.
*
* @param providerId A provider ID string.
* @return An {@code ApiFuture} which will complete successfully when the specified provider
* config has been deleted. If an error occurs while deleting the provider config, the future
* throws a {@link FirebaseAuthException}.
* @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed
* with "saml.".
*/
public ApiFuture<Void> deleteSamlProviderConfigAsync(String providerId) {
return deleteSamlProviderConfigOp(providerId).callAsync(firebaseApp);
}

private CallableOperation<Void, FirebaseAuthException> deleteSamlProviderConfigOp(
final String providerId) {
checkNotDestroyed();
SamlProviderConfig.checkSamlProviderId(providerId);
final FirebaseUserManager userManager = getUserManager();
return new CallableOperation<Void, FirebaseAuthException>() {
@Override
protected Void execute() throws FirebaseAuthException {
userManager.deleteSamlProviderConfig(providerId);
return null;
}
};
}

FirebaseApp getFirebaseApp() {
return this.firebaseApp;
}
Expand Down
25 changes: 22 additions & 3 deletions src/main/java/com/google/firebase/auth/FirebaseUserManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ Tenant createTenant(Tenant.CreateRequest request) throws FirebaseAuthException {

Tenant updateTenant(Tenant.UpdateRequest request) throws FirebaseAuthException {
Map<String, Object> properties = request.getProperties();
// TODO(micahstairs): Move this check so that argument validation happens outside the
// CallableOperation.
checkArgument(!properties.isEmpty(), "tenant update must have at least one property set");
GenericUrl url = new GenericUrl(tenantMgtBaseUrl + getTenantUrlSuffix(request.getTenantId()));
url.put("updateMask", generateMask(properties));
Expand Down Expand Up @@ -318,15 +320,22 @@ String getEmailActionLink(EmailLinkType type, String email,
OidcProviderConfig createOidcProviderConfig(
OidcProviderConfig.CreateRequest request) throws FirebaseAuthException {
GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + "/oauthIdpConfigs");
String providerId = request.getProviderId();
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
url.set("oauthIdpConfigId", providerId);
url.set("oauthIdpConfigId", request.getProviderId());
return sendRequest("POST", url, request.getProperties(), OidcProviderConfig.class);
}

SamlProviderConfig createSamlProviderConfig(
SamlProviderConfig.CreateRequest request) throws FirebaseAuthException {
GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + "/inboundSamlConfigs");
url.set("inboundSamlConfigId", request.getProviderId());
return sendRequest("POST", url, request.getProperties(), SamlProviderConfig.class);
}

OidcProviderConfig updateOidcProviderConfig(OidcProviderConfig.UpdateRequest request)
throws FirebaseAuthException {
Map<String, Object> properties = request.getProperties();
// TODO(micahstairs): Move this check so that argument validation happens outside the
// CallableOperation.
checkArgument(!properties.isEmpty(),
"Provider config update must have at least one property set.");
GenericUrl url =
Expand Down Expand Up @@ -365,6 +374,11 @@ void deleteOidcProviderConfig(String providerId) throws FirebaseAuthException {
sendRequest("DELETE", url, null, GenericJson.class);
}

void deleteSamlProviderConfig(String providerId) throws FirebaseAuthException {
GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + getSamlUrlSuffix(providerId));
sendRequest("DELETE", url, null, GenericJson.class);
}

private static String generateMask(Map<String, Object> properties) {
// This implementation does not currently handle the case of nested properties. This is fine
// since we do not currently generate masks for any properties with nested values. When it
Expand All @@ -383,6 +397,11 @@ private static String getOidcUrlSuffix(String providerId) {
return "/oauthIdpConfigs/" + providerId;
}

private static String getSamlUrlSuffix(String providerId) {
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
return "/inboundSamlConfigs/" + providerId;
}

private <T> T post(String path, Object content, Class<T> clazz) throws FirebaseAuthException {
checkArgument(!Strings.isNullOrEmpty(path), "path must not be null or empty");
checkNotNull(content, "content must not be null for POST requests");
Expand Down
25 changes: 20 additions & 5 deletions src/main/java/com/google/firebase/auth/OidcProviderConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public UpdateRequest updateRequest() {
return new UpdateRequest(getProviderId());
}

static void checkOidcProviderId(String providerId) {
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
checkArgument(providerId.startsWith("oidc."),
"Invalid OIDC provider ID (must be prefixed with 'oidc.'): " + providerId);
}

/**
* A specification class for creating a new OIDC Auth provider.
*
Expand All @@ -71,6 +77,19 @@ public static final class CreateRequest extends AbstractCreateRequest<CreateRequ
*/
public CreateRequest() { }

/**
* Sets the ID for the new provider.
*
* @param providerId A non-null, non-empty provider ID string.
* @throws IllegalArgumentException If the provider ID is null or empty, or is not prefixed with
* 'oidc.'.
*/
@Override
public CreateRequest setProviderId(String providerId) {
checkOidcProviderId(providerId);
return super.setProviderId(providerId);
}

/**
* Sets the client ID for the new provider.
*
Expand Down Expand Up @@ -100,10 +119,6 @@ public CreateRequest setIssuer(String issuer) {
CreateRequest getThis() {
return this;
}

void assertValidProviderIdFormat(String providerId) {
checkArgument(providerId.startsWith("oidc."), "Invalid OIDC provider ID: " + providerId);
}
}

/**
Expand All @@ -129,7 +144,7 @@ public static final class UpdateRequest extends AbstractUpdateRequest<UpdateRequ
*/
public UpdateRequest(String providerId) {
super(providerId);
checkArgument(providerId.startsWith("oidc."), "Invalid OIDC provider ID: " + providerId);
checkOidcProviderId(providerId);
}

/**
Expand Down
14 changes: 1 addition & 13 deletions src/main/java/com/google/firebase/auth/ProviderConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,7 @@ public abstract static class AbstractCreateRequest<T extends AbstractCreateReque
final Map<String,Object> properties = new HashMap<>();
String providerId;

/**
* Sets the ID for the new provider.
*
* @param providerId A non-null, non-empty provider ID string.
* @throws IllegalArgumentException If the provider ID is null or empty, or if the format is
* invalid.
*/
public T setProviderId(String providerId) {
checkArgument(
!Strings.isNullOrEmpty(providerId), "Provider ID name must not be null or empty.");
assertValidProviderIdFormat(providerId);
T setProviderId(String providerId) {
this.providerId = providerId;
return getThis();
}
Expand Down Expand Up @@ -117,8 +107,6 @@ Map<String, Object> getProperties() {
}

abstract T getThis();

abstract void assertValidProviderIdFormat(String providerId);
}

/**
Expand Down
23 changes: 19 additions & 4 deletions src/main/java/com/google/firebase/auth/SamlProviderConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ public String getCallbackUrl() {
return (String) spConfig.get("callbackUri");
}

static void checkSamlProviderId(String providerId) {
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
checkArgument(providerId.startsWith("saml."),
"Invalid SAML provider ID (must be prefixed with 'saml.'): " + providerId);
}

private static List<Object> ensureNestedList(Map<String, Object> outerMap, String id) {
List<Object> list = (List<Object>) outerMap.get(id);
if (list == null) {
Expand Down Expand Up @@ -106,6 +112,19 @@ public static final class CreateRequest extends AbstractCreateRequest<CreateRequ
*/
public CreateRequest() { }

/**
* Sets the ID for the new provider.
*
* @param providerId A non-null, non-empty provider ID string.
* @throws IllegalArgumentException If the provider ID is null or empty, or is not prefixed with
* 'saml.'.
*/
@Override
public CreateRequest setProviderId(String providerId) {
checkSamlProviderId(providerId);
return super.setProviderId(providerId);
}

/**
* Sets the IDP entity ID for the new provider.
*
Expand Down Expand Up @@ -181,9 +200,5 @@ public CreateRequest setCallbackUrl(String callbackUrl) {
CreateRequest getThis() {
return this;
}

void assertValidProviderIdFormat(String providerId) {
checkArgument(providerId.startsWith("saml."), "Invalid SAML provider ID: " + providerId);
}
}
}
Loading