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

    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.

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

= Security Introduction
:description: Helidon Security introduction
:keywords: helidon, security

Helidon Security provides the following features

. Authentication - support for authenticating incoming requests, creating a
 security Subject with Principal and Grants. Principal represents current user/service.
 Grant may represent a Role, Scope etc.
 Responsibility to create Principals and Grants lies with with AuthenticationProvider
 SPI. The following Principals are expected and supported out of the box:
.. UserPrincipal - the party is an end-user (e.g. a person) - there can be zero to
 one user principals in a subject
.. ServicePrincipal - the party is a service (e.g. a computer program) - there can
 be zero to one service principals in a subject
. Authorization - support for authorizing incoming requests. Out-of-the-box the
 security module supports ABAC and RBAC (Attribute based access control and Role based
 access control). RBAC is handled through RolesAllowed annotation (for integrations that
 support injection).
. Outbound security - support for propagating identity or (in general) securing
 outbound requests. Modification of a request to include outbound security is
 responsibility of OutboundSecurityProvider SPI
. Audit - security module audits most important events through its own API
 (e.g. Authentication events, Authorization events, outbound security events).
 A default AuditProvider is provided as well, logging to Java util logging (JUL)
 logger called "AUDIT" (may be overridden through configuration). AuditProvider
 SPI may be implemented to support other auditing options.

Security module is quite HTTP centric (as most common use cases are related to
 HTTP REST), though it is not HTTP specific (the security module may be used to
 secure even other transports, such as JMS, Kafka messages etc. if an appropriate
 integration module is developed, as all APIs can be mapped to a non-HTTP
 protocol). Nevertheless there may be security providers that only make sense with
 HTTP (such as HTTP digest authentication).

== How to use

To integrate with a container, or to use Security standalone, we must
 create an instance of security.
In general, Security supports three approaches

- a fluent-API builder pattern - you configure everything "by hand"
- a configuration based pattern - you configure everything in a configuration file
- hybrid - you load a builder from configuration and update it in a program

Once a security instance is built, it can be used to initialize an
 <<_cloud_security_container_integrations,integration with a container>>, or to
 use security from a program directly:

[source,java]
.Security direct usage
----
// create a security context
SecurityContext context = security.contextBuilder(UUID.randomUUID().toString())
                .env(SecurityEnvironment.builder()
                             .method("get")
                             .path("/test")
                             .transport("http")
                             .header("Authorization", "Bearer abcdefgh")
                             .build())
                .build();

// use the context to authenticate a request
context.atnClientBuilder()
                .submit()
                .whenComplete((response, exception) -> {
                    // this is to show the features, not a real-world production code...
                    if (null == exception) {
                        if (response.getStatus().isSuccess()) {
                            System.out.println(response.getUser());
                            System.out.println(response.getService());
                        } else {
                            System.out.println("Authentication failed: " + response.getDescription());
                        }
                    } else {
                        exception.printStackTrace();
                    }
                });
----

=== Builder pattern

[source,java]
.Security through a builder
----
Security security = Security.builder()
        // create a provider instance based on the provider documentation
        .addProvider(...)
        .build();
----

=== Configuration pattern

See <<_tools,Secure config>> for details about encrypting passwords in
 configuration files.

[source,java]
.Security from configuration
----
// uses io.helidon.Config
Security security = Security.create(config);
----

[source,conf]
.Security from configuration - configuration
----
# Uses config encryption filter to encrypt passwords
security.providers: [
    {
        http-basic-auth {
            realm = "helidon"

            user-store {
                users: [
                    {
                        login = "aUser"
                        password = "${CLEAR=somePassword}"
                        roles = ["theRole"]

                    },
                    {
                        login = "noRoles"
                        password = "${CLEAR=somePassword}"
                        roles = []
                    }
                ]
            }
        }
    }
]
----

=== Hybrid pattern (Builder & Configuration)

[source,java]
.Security from configuration and builder
----
// uses io.helidon.Config
Security security = Security.builder(config)
                .addProvider(...)
                .build();

// or reverse order:
Security security = Security.builder()
                .addProvider()
                .config(config)
                .build();
----

== Maven Coordinates

You need to declare the following dependency in your project:

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