io.helidon.security.providers.httpauth.HttpBasicAuthProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of helidon-security-providers-http-auth Show documentation
Show all versions of helidon-security-providers-http-auth Show documentation
HTTP basic and digest authentication provider
/*
* Copyright (c) 2018, 2020 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.providers.httpauth;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.helidon.common.HelidonFeatures;
import io.helidon.common.serviceloader.HelidonServiceLoader;
import io.helidon.config.Config;
import io.helidon.security.AuthenticationResponse;
import io.helidon.security.EndpointConfig;
import io.helidon.security.OutboundSecurityResponse;
import io.helidon.security.Principal;
import io.helidon.security.ProviderRequest;
import io.helidon.security.Role;
import io.helidon.security.SecurityContext;
import io.helidon.security.SecurityEnvironment;
import io.helidon.security.Subject;
import io.helidon.security.SubjectType;
import io.helidon.security.providers.httpauth.spi.UserStoreService;
import io.helidon.security.spi.AuthenticationProvider;
import io.helidon.security.spi.OutboundSecurityProvider;
import io.helidon.security.spi.SynchronousProvider;
/**
* Http authentication security provider.
* Provides support for username and password authentication, with support for roles list.
*/
public class HttpBasicAuthProvider extends SynchronousProvider implements AuthenticationProvider, OutboundSecurityProvider {
/**
* Configure this for outbound requests to override user to use.
*/
public static final String EP_PROPERTY_OUTBOUND_USER = "io.helidon.security.outbound.user";
/**
* Configure this for outbound requests to override password to use.
*/
public static final String EP_PROPERTY_OUTBOUND_PASSWORD = "io.helidon.security.outbound.password";
static final String HEADER_AUTHENTICATION_REQUIRED = "WWW-Authenticate";
static final String HEADER_AUTHENTICATION = "authorization";
static final String BASIC_PREFIX = "basic ";
private static final Logger LOGGER = Logger.getLogger(HttpBasicAuthProvider.class.getName());
private static final Pattern CREDENTIAL_PATTERN = Pattern.compile("(.*):(.*)");
private static final char[] EMPTY_PASSWORD = new char[0];
static {
HelidonFeatures.register("Security", "Authentication", "Basic-Auth");
HelidonFeatures.register("Security", "Outbound", "Basic-Auth");
}
private final List userStores;
private final String realm;
private final SubjectType subjectType;
HttpBasicAuthProvider(Builder builder) {
this.userStores = new LinkedList<>(builder.userStores);
this.realm = builder.realm;
this.subjectType = builder.subjectType;
}
/**
* Get a builder instance to construct a new security provider.
* Alternative approach is {@link #create(Config)} (or {@link HttpBasicAuthProvider#create(Config)}).
*
* @return builder to fluently construct Basic security provider
*/
public static Builder builder() {
return new Builder();
}
/**
* Load this provider from configuration.
*
* @param config Configuration located at this provider's configuration (e.g. child is either http-basic-auth or
* http-digest-auth)
* @return instance of provider configured from provided config
*/
public static HttpBasicAuthProvider create(Config config) {
return builder().config(config).build();
}
private static OutboundSecurityResponse toBasicAuthOutbound(String username, char[] password) {
String b64 = Base64.getEncoder()
.encodeToString((username + ":" + new String(password)).getBytes(StandardCharsets.UTF_8));
String basicAuthB64 = "basic " + b64;
return OutboundSecurityResponse
.withHeaders(Map.of("Authorization", List.of(basicAuthB64)));
}
@Override
public boolean isOutboundSupported(ProviderRequest providerRequest,
SecurityEnvironment outbondEnv,
EndpointConfig outboundEp) {
// explicitly overridden username and/or password
if (outboundEp.abacAttributeNames().contains(EP_PROPERTY_OUTBOUND_USER)) {
return true;
}
SecurityContext secContext = providerRequest.securityContext();
boolean userSupported = secContext.user()
.flatMap(user -> user.privateCredential(BasicPrivateCredentials.class))
.isPresent();
boolean serviceSupported = secContext.service()
.map(user -> user.privateCredential(BasicPrivateCredentials.class))
.isPresent();
return userSupported || serviceSupported;
}
@Override
protected OutboundSecurityResponse syncOutbound(ProviderRequest providerRequest,
SecurityEnvironment outboundEnv,
EndpointConfig outboundEp) {
// first resolve user to use
Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy