///////////////////////////////////////////////////////////////////////////////

    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.
    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.

///////////////////////////////////////////////////////////////////////////////

= Containers Integration
:description: Helidon Security containers integration
:keywords: helidon, security

== Cloud Security Container Integrations

The following containers are integrated with Helidon Security:

=== Web server

Integration of <<webserver/01_introduction.adoc,reactive web server>>

[source,xml]
.Maven Dependency
----
<dependency>
    <groupId>io.helidon.security.integration</groupId>
    <artifactId>helidon-security-integration-webserver</artifactId>
</dependency>
----

==== Bootstrapping

There are two steps to configure security with web server:

1. Create security instance and register it with server
2. Protect routes of web server with various security features

[source,java]
.Example using builders
----
// web server's Routing
Routing.builder()
    // This is step 1 - register security instance with web server processing
    // security - instance of security either from config or from a builder
    // securityDefaults - default enforcement for each route that has a security definition
    .register(WebSecurity.create(security).securityDefaults(WebSecurity.authenticate()))
    // this is step 2 - protect a route
    // protect this route with authentication (from defaults) and role "user"
    .get("/service1", WebSecurity.rolesAllowed("user"), (req, res) -> {
        processService1Request(req, res);
    })
    .build();
----

[source,java]
.Example using configuration
----
Routing.builder()
    // helper method to load both security and web server security from configuration
    .register(WebSecurity.create(config))
    // continue with web server route configuration
    .build();
----

[source,conf]
.Example using configuration - configuration (HOCON)
----
# This may change in the future - to align with web server configuration, once it is supported
security.web-server {
    # Configuration of integration with web server
    defaults {
        authenticate = true
    }
    paths: [
        {
            path = "/service1"
            methods = ["get"]
            roles-allowed = ["user"]
        }
    ]
}
----


=== Jersey

Integration of Jersey (JAX-RS implementation) both for inbound and outbound security.

[source,xml]
.Maven Dependency
----
<dependency>
    <groupId>io.helidon.security.integration</groupId>
    <artifactId>helidon-security-integration-jersey</artifactId>
</dependency>
----

==== Inbound security

[source,java]
.Integrate with Jersey
----
ResourceConfig resourceConfig = new ResourceConfig()
    // register JAX-RS resource
    .register(JaxRsResource.class)
    // integrate security
    .register(new io.helidon.security.jersey.SecurityFeature(security));
----

=== Protecting a resource

The current approach does not have a configuration option. The security must be
 configured through annotations.
Security currently supports @Authenticated and @Authorized. When a resource is annotated with one of these
 annotations (application class, resource class, or resource method), security will
 be triggered.

[source,java]
.Securing a resource method
----
// this is sufficient for security to be triggered, see javadoc for further details
@Authenticated
@Path("/{name}")
@GET
@Produces(MediaType.TEXT_PLAIN)
// due to Jersey approach to path matching, we need two methods to match both the "root" and "root" + subpaths
public String getHelloName(@PathParam("name") String name) {
    return "Hello " + name + ", your current subject: " + securityContext.getSubject();
}
----

=== Access context

[source,java]
.Support in a JAX-RS resource
----
// inject io.helidon.security.SecurityContext
@Context
private SecurityContext securityContext;

----


==== Outbound security

[source,java]
.Call remote target with outbound security
----
// I expect you have injected the ClientSecurityFeature as shown above
Client client = ClientBuilder.newClient()
    // integrate security
    .register(new ClientSecurityFeature());

try {
    // call the resource, will propagate identity as configured in Security
    String response = client.target("http://www.google.com")
        .request()
        // configure the security context for this request (as client and targets may be re-used)
        .property(ClientSecurityFeature.PROPERTY_CONTEXT, securityContext)
        .get(String.class);
} finally {
    client.close();
}
----

