From 3114eba77093d7ab012f8d97136dc03eb27a8a17 Mon Sep 17 00:00:00 2001 From: Nick Palladino Date: Fri, 4 Jun 2021 13:08:10 -0400 Subject: [PATCH 1/2] initial hackathon changes --- .../api/v1/controller/TokenController.java | 74 ---------- .../BrapiAuthorizeController.java | 9 +- .../brapi/auth/TokenController.java | 132 ++++++++++++++++++ src/main/resources/application.yml | 3 + 4 files changed, 139 insertions(+), 79 deletions(-) delete mode 100644 src/main/java/org/breedinginsight/api/v1/controller/TokenController.java rename src/main/java/org/breedinginsight/brapi/{v1/controller => auth}/BrapiAuthorizeController.java (83%) create mode 100644 src/main/java/org/breedinginsight/brapi/auth/TokenController.java diff --git a/src/main/java/org/breedinginsight/api/v1/controller/TokenController.java b/src/main/java/org/breedinginsight/api/v1/controller/TokenController.java deleted file mode 100644 index e1356dbfd..000000000 --- a/src/main/java/org/breedinginsight/api/v1/controller/TokenController.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.breedinginsight.api.v1.controller; - -import io.micronaut.http.HttpResponse; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.QueryValue; -import io.micronaut.http.uri.UriBuilder; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import lombok.extern.slf4j.Slf4j; -import org.breedinginsight.api.auth.AuthenticatedUser; -import org.breedinginsight.api.auth.SecurityService; -import org.breedinginsight.model.ApiToken; -import org.breedinginsight.services.TokenService; - -import javax.inject.Inject; -import javax.validation.constraints.NotBlank; -import java.net.URI; -import java.util.Optional; - -@Slf4j -@Controller("/${micronaut.bi.api.version}") -public class TokenController { - - private SecurityService securityService; - private TokenService tokenService; - - @Inject - public TokenController(SecurityService securityService, TokenService tokenService) { - this.securityService = securityService; - this.tokenService = tokenService; - } - - @Get("/api-token") - @Secured(SecurityRule.IS_AUTHENTICATED) - public HttpResponse apiToken(@QueryValue @NotBlank String returnUrl) { - - AuthenticatedUser actingUser = securityService.getUser(); - Optional token = tokenService.generateApiToken(actingUser); - - if(token.isPresent()) { - ApiToken apiToken = token.get(); - - URI location = UriBuilder.of(returnUrl) - .queryParam("status", 200) - .queryParam("token", apiToken.getAccessToken()) - .build(); - - return HttpResponse.seeOther(location) - .header("Cache-Control","no-store") - .header("Pragma", "no-cache"); - } else { - return HttpResponse.serverError(); - } - - } - -} diff --git a/src/main/java/org/breedinginsight/brapi/v1/controller/BrapiAuthorizeController.java b/src/main/java/org/breedinginsight/brapi/auth/BrapiAuthorizeController.java similarity index 83% rename from src/main/java/org/breedinginsight/brapi/v1/controller/BrapiAuthorizeController.java rename to src/main/java/org/breedinginsight/brapi/auth/BrapiAuthorizeController.java index 214890c8d..eda00965a 100644 --- a/src/main/java/org/breedinginsight/brapi/v1/controller/BrapiAuthorizeController.java +++ b/src/main/java/org/breedinginsight/brapi/auth/BrapiAuthorizeController.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.breedinginsight.brapi.v1.controller; +package org.breedinginsight.brapi.auth; import io.micronaut.context.annotation.Property; import io.micronaut.http.HttpResponse; @@ -45,12 +45,11 @@ public class BrapiAuthorizeController { @Get("/programs/{programId}/brapi/authorize") @Secured(SecurityRule.IS_ANONYMOUS) - public HttpResponse authorize(@QueryValue @NotBlank String display_name, @QueryValue @NotBlank String return_url, @PathVariable("programId") String programId) { + public HttpResponse authorize(@QueryValue @NotBlank String client_id, @QueryValue @NotBlank String redirect_uri, @PathVariable("programId") String programId) { URI location = UriBuilder.of(String.format("%s/programs/%s/brapi/authorize", webBaseUrl, programId)) - .queryParam("display_name", display_name) - .queryParam("return_url", return_url) + .queryParam("display_name", client_id) + .queryParam("return_url", redirect_uri) .build(); return HttpResponse.seeOther(location); } - } diff --git a/src/main/java/org/breedinginsight/brapi/auth/TokenController.java b/src/main/java/org/breedinginsight/brapi/auth/TokenController.java new file mode 100644 index 000000000..574e5a96c --- /dev/null +++ b/src/main/java/org/breedinginsight/brapi/auth/TokenController.java @@ -0,0 +1,132 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.breedinginsight.brapi.auth; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import io.micronaut.context.annotation.Property; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.QueryValue; +import io.micronaut.http.uri.UriBuilder; +import io.micronaut.security.annotation.Secured; +import io.micronaut.security.rules.SecurityRule; +import lombok.extern.slf4j.Slf4j; +import org.breedinginsight.api.auth.AuthenticatedUser; +import org.breedinginsight.api.auth.SecurityService; +import org.breedinginsight.model.ApiToken; +import org.breedinginsight.services.TokenService; + +import javax.inject.Inject; +import javax.validation.constraints.NotBlank; +import java.net.URI; +import java.util.Optional; +import java.util.UUID; + +@Slf4j +@Controller("/${micronaut.bi.api.version}") +public class TokenController { + + private SecurityService securityService; + private TokenService tokenService; + + @Property(name = "backend.base-url") + protected String backendBaseUrl; + + @Property(name = "micronaut.bi.api.version") + protected String biapiVersion; + + @Inject + public TokenController(SecurityService securityService, TokenService tokenService) { + this.securityService = securityService; + this.tokenService = tokenService; + } + + @Get("/api-token") + @Secured(SecurityRule.IS_AUTHENTICATED) + public HttpResponse apiToken(@QueryValue @NotBlank String returnUrl) { + + AuthenticatedUser actingUser = securityService.getUser(); + Optional token = tokenService.generateApiToken(actingUser); + + // FieldBook sends user to brapi-authorize endpoint + // brapi authorize endpoint sends user to bi-web authorization page + // User logs in and is redirected to orcid + // User logs into orcid + // Orcid back to bi-api authorization flow + // Bi-api returns user to that authorization page + // User sees fieldbook authorize page on bi-web + // User clicks authorize button + // bi-web sends user to this endpoint + + if(token.isPresent()) { + ApiToken apiToken = token.get(); + + URI location = UriBuilder.of(returnUrl) + .queryParam("status", 200) + .queryParam("access_token", apiToken.getAccessToken()) + .build(); + + return HttpResponse.seeOther(location) + .header("Cache-Control","no-store") + .header("Pragma", "no-cache"); + } else { + return HttpResponse.serverError(); + } + } + + @Get("/programs/{programId}/.well-known/openid-configuration") + @Secured(SecurityRule.IS_ANONYMOUS) + public HttpResponse getConfiguration(@PathVariable("programId") UUID programId) { + + /* + { + "issuer": "", + "authorization_endpoint": "", + "jwks_uri": "", + "token_endpoint": "", + "grant_types_supported": ["implicit"], + "response_types_supported": ["token"], + "subject_types_supported": ["public"], + "id_token_signing_alg_values_supported": [] + } + */ + JsonObject configuration = new JsonObject(); + configuration.add("issuer", new JsonPrimitive("")); + String authorizeUrl = String.format("%s/%s/programs/%s/brapi/authorize", backendBaseUrl, biapiVersion, programId); + configuration.add("authorization_endpoint", new JsonPrimitive(authorizeUrl)); + configuration.add("jwks_uri", new JsonPrimitive("")); + configuration.add("token_endpoint", new JsonPrimitive("")); + JsonArray grants = new JsonArray(); + grants.add("implict"); + configuration.add("grant_types_supported", grants); + JsonArray responseTypes = new JsonArray(); + responseTypes.add("token"); + configuration.add("response_types_supported", responseTypes); + JsonArray subjectTypes = new JsonArray(); + subjectTypes.add("public"); + configuration.add("subject_types_supported", subjectTypes); + JsonArray signingValues = new JsonArray(); + configuration.add("id_token_signing_alg_values_supported", signingValues); + + return HttpResponse.ok(configuration); + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b7c035f46..be53508ba 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -140,6 +140,9 @@ web: error: url: ${web.base-url}/account-error +backend: + base-url: ${WEB_BASE_URL:`http://localhost:8081`} + brapi: server: default-url: ${BRAPI_DEFAULT_URL:`https://test-server.brapi.org`} From f23ed4b8e849985219719d4c7075a644abadb6ea Mon Sep 17 00:00:00 2001 From: Chris T Date: Fri, 4 Jun 2021 13:32:04 -0400 Subject: [PATCH 2/2] fix open id config endpoint --- .../brapi/auth/TokenController.java | 26 +++++++------- .../brapi/auth/model/OpenIdConfiguration.java | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/breedinginsight/brapi/auth/model/OpenIdConfiguration.java diff --git a/src/main/java/org/breedinginsight/brapi/auth/TokenController.java b/src/main/java/org/breedinginsight/brapi/auth/TokenController.java index 574e5a96c..c825761e4 100644 --- a/src/main/java/org/breedinginsight/brapi/auth/TokenController.java +++ b/src/main/java/org/breedinginsight/brapi/auth/TokenController.java @@ -31,12 +31,15 @@ import lombok.extern.slf4j.Slf4j; import org.breedinginsight.api.auth.AuthenticatedUser; import org.breedinginsight.api.auth.SecurityService; +import org.breedinginsight.brapi.auth.model.OpenIdConfiguration; import org.breedinginsight.model.ApiToken; import org.breedinginsight.services.TokenService; import javax.inject.Inject; import javax.validation.constraints.NotBlank; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -94,7 +97,7 @@ public HttpResponse apiToken(@QueryValue @NotBlank String returnUrl) { @Get("/programs/{programId}/.well-known/openid-configuration") @Secured(SecurityRule.IS_ANONYMOUS) - public HttpResponse getConfiguration(@PathVariable("programId") UUID programId) { + public HttpResponse getConfiguration(@PathVariable("programId") UUID programId) { /* { @@ -108,23 +111,20 @@ public HttpResponse getConfiguration(@PathVariable("programId") UUID programId) "id_token_signing_alg_values_supported": [] } */ - JsonObject configuration = new JsonObject(); - configuration.add("issuer", new JsonPrimitive("")); + OpenIdConfiguration configuration = new OpenIdConfiguration(); + configuration.setIssuer(""); String authorizeUrl = String.format("%s/%s/programs/%s/brapi/authorize", backendBaseUrl, biapiVersion, programId); - configuration.add("authorization_endpoint", new JsonPrimitive(authorizeUrl)); - configuration.add("jwks_uri", new JsonPrimitive("")); - configuration.add("token_endpoint", new JsonPrimitive("")); - JsonArray grants = new JsonArray(); - grants.add("implict"); - configuration.add("grant_types_supported", grants); + configuration.setAuthorization_endpoint(authorizeUrl); + configuration.setJwks_uri(""); + configuration.setToken_endpoint(""); + configuration.setGrant_types_supported(List.of("implicit")); JsonArray responseTypes = new JsonArray(); responseTypes.add("token"); - configuration.add("response_types_supported", responseTypes); + configuration.setResponse_types_supported(List.of("token")); JsonArray subjectTypes = new JsonArray(); subjectTypes.add("public"); - configuration.add("subject_types_supported", subjectTypes); - JsonArray signingValues = new JsonArray(); - configuration.add("id_token_signing_alg_values_supported", signingValues); + configuration.setSubject_types_supported(List.of("public")); + configuration.setId_token_signing_alg_values_supported(new ArrayList()); return HttpResponse.ok(configuration); } diff --git a/src/main/java/org/breedinginsight/brapi/auth/model/OpenIdConfiguration.java b/src/main/java/org/breedinginsight/brapi/auth/model/OpenIdConfiguration.java new file mode 100644 index 000000000..82bf7292b --- /dev/null +++ b/src/main/java/org/breedinginsight/brapi/auth/model/OpenIdConfiguration.java @@ -0,0 +1,36 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.breedinginsight.brapi.auth.model; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class OpenIdConfiguration { + String issuer; + String authorization_endpoint; + String jwks_uri; + String token_endpoint; + List grant_types_supported; + List response_types_supported; + List subject_types_supported; + List id_token_signing_alg_values_supported; +}