diff --git a/examples/security/oidc/README.md b/examples/security/oidc/README.md new file mode 100644 index 00000000000..404a55c3fe0 --- /dev/null +++ b/examples/security/oidc/README.md @@ -0,0 +1,23 @@ +Security integration with OIDC +=================== + +This example demonstrates integration with OIDC (Open ID Connect) providers. + +Contents +-------- +MP example that integrates with an OIDC provider. + +To configure this example, you need to replace the following: +1. src/main/resources/application.yaml - set security.properties.oidc-* to your tenant and application configuration + +Running the Example +------------------- + +Run the "OidcMain" class for file configuration based example. + + +Local configuration +------------------ +The example is already set up to read +`${user.home}/helidon/conf/examples.yaml` to override defaults configured +in `application.yaml`. diff --git a/examples/security/oidc/pom.xml b/examples/security/oidc/pom.xml new file mode 100644 index 00000000000..a2b64c9ea6d --- /dev/null +++ b/examples/security/oidc/pom.xml @@ -0,0 +1,59 @@ + + + + + 4.0.0 + + io.helidon.examples.security + helidon-examples-security-project + 1.0.4-SNAPSHOT + + + oidc-login + Helidon Security Examples OIDC + + + Example of login using (any) OIDC provider. + + + + io.helidon.security.examples.oidc.OidcMain + + + + + + io.helidon.microprofile.bundles + helidon-microprofile-1.2 + ${project.version} + + + + io.helidon.microprofile + helidon-microprofile-security + ${project.version} + + + io.helidon.microprofile + helidon-microprofile-oidc + ${project.version} + + + + \ No newline at end of file diff --git a/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcMain.java b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcMain.java new file mode 100644 index 00000000000..9fad47cd20d --- /dev/null +++ b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcMain.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * + * 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 io.helidon.security.examples.oidc; + +import java.io.IOException; +import java.util.logging.LogManager; + +import io.helidon.config.Config; +import io.helidon.microprofile.server.Server; + +import static io.helidon.config.ConfigSources.classpath; +import static io.helidon.config.ConfigSources.file; + +/** + * Main class for MP. + */ +public final class OidcMain { + private OidcMain() { + } + + /** + * Start the application. + * @param args ignored. + * @throws IOException in case the logging configuration fails + */ + public static void main(String[] args) throws IOException { + LogManager.getLogManager().readConfiguration(OidcMain.class.getResourceAsStream("/logging.properties")); + + Server server = Server.builder() + .config(buildConfig()) + .build() + .start(); + + System.out.println("http://localhost:" + server.port() + "/test"); + } + + private static Config buildConfig() { + return Config.builder() + .sources( + // you can use this file to override the defaults that are built-in + file(System.getProperty("user.home") + "/helidon/conf/examples.yaml").optional(), + // in jar file (see src/main/resources/application.yaml) + classpath("application.yaml")) + .build(); + } +} diff --git a/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcResource.java b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcResource.java new file mode 100644 index 00000000000..9a059c8fbdd --- /dev/null +++ b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcResource.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * + * 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 io.helidon.security.examples.oidc; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Context; + +import io.helidon.security.SecurityContext; +import io.helidon.security.annotations.Authenticated; + +/** + * A simple JAX-RS resource with a single GET method. + */ +@Path("/test") +public class OidcResource { + + /** + * Hello world using security context. + * @param securityContext context as established during login + * @return a string with current username + */ + @Authenticated + @GET + public String getIt(@Context SecurityContext securityContext) { + return "Hello " + securityContext.userName(); + } + +} diff --git a/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcTestApplication.java b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcTestApplication.java new file mode 100644 index 00000000000..172efe55b14 --- /dev/null +++ b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/OidcTestApplication.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * + * 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 io.helidon.security.examples.oidc; + +import java.util.Set; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +import io.helidon.common.CollectionsHelper; + +/** + * A simple JAX-rs application that just returns the single {@link io.helidon.security.examples.oidc.OidcResource resource}. + */ +@ApplicationScoped +@ApplicationPath("/") +public class OidcTestApplication extends Application { + + @Override + public Set> getClasses() { + return CollectionsHelper.setOf(OidcResource.class); + } +} diff --git a/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/package-info.java b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/package-info.java new file mode 100644 index 00000000000..98d86de2055 --- /dev/null +++ b/examples/security/oidc/src/main/java/io/helidon/security/examples/oidc/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * + * 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. + */ +/** + * An OIDC (Open ID Connect) example. + */ +package io.helidon.security.examples.oidc; diff --git a/examples/security/oidc/src/main/resources/META-INF/beans.xml b/examples/security/oidc/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..30696f939e8 --- /dev/null +++ b/examples/security/oidc/src/main/resources/META-INF/beans.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/examples/security/oidc/src/main/resources/application.yaml b/examples/security/oidc/src/main/resources/application.yaml new file mode 100644 index 00000000000..ec96813ccd5 --- /dev/null +++ b/examples/security/oidc/src/main/resources/application.yaml @@ -0,0 +1,49 @@ +# +# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# +# 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. +# + +server: + port: 7987 +security: + config.require-encryption: false + properties: + # this should be defined by the identity server + oidc-identity-uri: "https://tenant.some-server.com/oauth2/default" + # when you create a new client in identity server configuration, you should get a client id and a client secret + oidc-client-id: "some client id" + oidc-client-secret: "some client secret" + # issuer of the tokens - identity server specific (maybe even configurable) + oidc-issuer: "https://tenant.some-server.com/oauth2/default" + # audience of the tokens - identity server specific (usually configurable) + oidc-audience: "configured audience" + # The frontend URI defines the possible load balancer address + # The redirect URI used is ${frontend-uri}${redirect-uri} + # Webserver is by default listening on /oidc/redirect - this can be modified by `redirect-uri` option in oidc configuration + frontend-uri: "http://localhost:7987" + providers: + - abac: + - oidc: + # use a custom name, so it does not clash with other examples + cookie-name: "OIDC_EXAMPLE_COOKIE" + # support for "Authorization" header with bearer token + header-use: true + # the default redirect-uri, where the webserver listens on redirects from identity server + redirect-uri: "/oidc/redirect" + issuer: "${ALIAS=security.properties.oidc-issuer}" + audience: "${ALIAS=security.properties.oidc-audience}" + client-id: "${ALIAS=security.properties.oidc-client-id}" + client-secret: "${ALIAS=security.properties.oidc-client-secret}" + identity-uri: "${ALIAS=security.properties.oidc-identity-uri}" + frontend-uri: "${ALIAS=security.properties.frontend-uri}" \ No newline at end of file diff --git a/examples/security/oidc/src/main/resources/logging.properties b/examples/security/oidc/src/main/resources/logging.properties new file mode 100644 index 00000000000..61f225dd918 --- /dev/null +++ b/examples/security/oidc/src/main/resources/logging.properties @@ -0,0 +1,26 @@ +# +# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# +# 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. +# + +handlers = java.util.logging.ConsoleHandler + +java.util.logging.ConsoleHandler.level = FINEST +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n + +.level = INFO +io.helidon.config.level = WARNING +# io.helidon.security.providers.oidc.level = FINEST +AUDIT.level=FINEST diff --git a/examples/security/pom.xml b/examples/security/pom.xml index d984b0eaf7d..ec4c1e656c7 100644 --- a/examples/security/pom.xml +++ b/examples/security/pom.xml @@ -45,6 +45,7 @@ attribute-based-access-control idcs-login outbound-override + oidc diff --git a/security/providers/oidc/src/main/java/io/helidon/security/providers/oidc/OidcSupport.java b/security/providers/oidc/src/main/java/io/helidon/security/providers/oidc/OidcSupport.java index 43e4c3ff4a0..5fa9874c318 100644 --- a/security/providers/oidc/src/main/java/io/helidon/security/providers/oidc/OidcSupport.java +++ b/security/providers/oidc/src/main/java/io/helidon/security/providers/oidc/OidcSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -177,6 +177,7 @@ private void processCode(String code, ServerRequest req, ServerResponse res) { MultivaluedHashMap formValues = new MultivaluedHashMap<>(); formValues.putSingle("grant_type", "authorization_code"); formValues.putSingle("code", code); + formValues.putSingle("redirect_uri", oidcConfig.redirectUriWithHost()); Response response = oidcConfig.tokenEndpoint().request() .accept(MediaType.APPLICATION_JSON_TYPE)