Search in sources :

Example 1 with BearerTokenCredential

use of org.dcache.auth.BearerTokenCredential in project dcache by dCache.

the class CopyFilter method fetchCredential.

private Object fetchCredential(CredentialSource source) throws InterruptedException, ErrorResponseException {
    Subject subject = Subject.getSubject(AccessController.getContext());
    switch(source) {
        case GRIDSITE:
            try {
                HttpServletRequest request = ServletRequest.getRequest();
                // Use the X.509 identity from TLS, even if that wasn't used to
                // establish the user's identity.  This allows the local activity of
                // the COPY (i.e., the ability to read a file, or create a new file)
                // to be authorized based on some non-X.509 identity, while using a
                // delegated X.509 credential when authenticating for the
                // third-party copy, based on the client credential presented when
                // establishing the TLS connection.
                Subject x509Subject = AuthenticationHandler.getX509Identity(request);
                String dn = x509Subject == null ? null : Subjects.getDn(x509Subject);
                if (dn == null) {
                    throw new ErrorResponseException(Response.Status.SC_UNAUTHORIZED, "user must present valid X.509 certificate");
                }
                String fqan = Objects.toString(Subjects.getPrimaryFqan(x509Subject), null);
                /* If delegation has been requested and declined then
                     * potentially use the existing delegated credential.  We don't
                     * want to artifically fail requests that might otherwise
                     * succeed.
                     */
                int minLifetimeInMinutes = hasClientAlreadyBeenRedirected(request) ? 2 : 20;
                return _credentialService.getDelegatedCredential(dn, fqan, minLifetimeInMinutes, MINUTES);
            } catch (PermissionDeniedCacheException e) {
                throw new ErrorResponseException(Status.SC_UNAUTHORIZED, "Presented X.509 certificate not valid");
            } catch (CacheException e) {
                throw new ErrorResponseException(Status.SC_INTERNAL_SERVER_ERROR, "Internal problem: " + e.getMessage());
            }
        case OIDC:
            BearerTokenCredential bearer = subject.getPrivateCredentials().stream().filter(BearerTokenCredential.class::isInstance).map(BearerTokenCredential.class::cast).findFirst().orElseThrow(() -> new ErrorResponseException(Status.SC_UNAUTHORIZED, "User must authenticate with OpenID for " + "OpenID delegation"));
            return _credentialService.getDelegatedCredential(bearer.getToken(), _oidcClientCredentials);
        case NONE:
            return null;
        default:
            throw new RuntimeException("Unsupported source " + source);
    }
}
Also used : HttpServletRequest(javax.servlet.http.HttpServletRequest) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) CacheException(diskCacheV111.util.CacheException) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) BearerTokenCredential(org.dcache.auth.BearerTokenCredential) Subject(javax.security.auth.Subject)

Example 2 with BearerTokenCredential

use of org.dcache.auth.BearerTokenCredential in project dcache by dCache.

the class SciTokenPlugin method authenticate.

@Override
public void authenticate(Set<Object> publicCredentials, Set<Object> privateCredentials, Set<Principal> identifiedPrincipals, Set<Restriction> restrictions) throws AuthenticationException {
    List<String> tokens = privateCredentials.stream().filter(BearerTokenCredential.class::isInstance).map(BearerTokenCredential.class::cast).map(BearerTokenCredential::getToken).filter(JsonWebToken::isCompatibleFormat).collect(Collectors.toList());
    checkAuthentication(!tokens.isEmpty(), "no JWT bearer token");
    checkAuthentication(tokens.size() == 1, "multiple JWT bearer tokens");
    try {
        JsonWebToken token = checkValid(new JsonWebToken(tokens.get(0)));
        Issuer issuer = issuerOf(token);
        validateWlcgVersionClaim(token);
        Collection<Principal> principals = new ArrayList<>();
        // REVISIT consider introducing an SPI to allow plugable support for handling claims.
        Optional<String> sub = token.getPayloadString("sub");
        sub.map(s -> new JwtSubPrincipal(issuer.getId(), s)).ifPresent(principals::add);
        sub.map(s -> new OidcSubjectPrincipal(s, issuer.getId())).ifPresent(principals::add);
        Optional<String> jti = token.getPayloadString("jti");
        jti.map(s -> new JwtJtiPrincipal(issuer.getId(), s)).ifPresent(principals::add);
        token.getPayloadStringOrArray("wlcg.groups").stream().map(OpenIdGroupPrincipal::new).forEach(principals::add);
        checkAuthentication(sub.isPresent() || jti.isPresent(), "missing sub and jti claims");
        principals.add(issuer.getOpIdentity());
        List<AuthorisationSupplier> scopes = token.getPayloadString("scope").map(SciTokenPlugin::parseScope).orElse(Collections.emptyList());
        if (scopes.isEmpty()) {
            // No scopes defined -> not explicit authorisation; however, perhaps the client
            // is allowed to do something based on asserted group-membership or from their
            // membership of the VO (implied by the OP issuing any token at all).
            // This only makes sense if the token follows the WLCG AuthZ profile.  A SciToken
            // is not valid (or useful) without at least one authorisation statements in the
            // 'scope' claim
            checkAuthentication(token.getPayloadString("wlcg.ver").isPresent(), "not a SciToken or WLCG profile.");
        // allow login to proceed with whatever information we've gained so far.
        } else {
            principals.addAll(issuer.getUserIdentity());
            Restriction r = buildRestriction(issuer.getPrefix(), scopes);
            LOGGER.debug("Authenticated user with restriction: {}", r);
            restrictions.add(r);
            principals.add(new ExemptFromNamespaceChecks());
        }
        identifiedPrincipals.addAll(principals);
    } catch (IOException e) {
        throw new AuthenticationException(e.getMessage());
    }
}
Also used : ExemptFromNamespaceChecks(org.dcache.auth.ExemptFromNamespaceChecks) MultiTargetedRestriction(org.dcache.auth.attributes.MultiTargetedRestriction) FsPath(diskCacheV111.util.FsPath) Restriction(org.dcache.auth.attributes.Restriction) Subjects(org.dcache.auth.Subjects) JwtSubPrincipal(org.dcache.auth.JwtSubPrincipal) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) OpenIdGroupPrincipal(org.dcache.auth.OpenIdGroupPrincipal) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) GPlazmaAuthenticationPlugin(org.dcache.gplazma.plugins.GPlazmaAuthenticationPlugin) HttpClient(org.apache.http.client.HttpClient) Objects.requireNonNull(java.util.Objects.requireNonNull) Map(java.util.Map) Authorisation(org.dcache.auth.attributes.MultiTargetedRestriction.Authorisation) Splitter(com.google.common.base.Splitter) EnumSet(java.util.EnumSet) OidcSubjectPrincipal(org.dcache.auth.OidcSubjectPrincipal) BearerTokenCredential(org.dcache.auth.BearerTokenCredential) ImmutableSet(com.google.common.collect.ImmutableSet) Properties(java.util.Properties) Logger(org.slf4j.Logger) Preconditions.checkAuthentication(org.dcache.gplazma.util.Preconditions.checkAuthentication) Collection(java.util.Collection) JsonWebToken(org.dcache.gplazma.util.JsonWebToken) Set(java.util.Set) IOException(java.io.IOException) JwtJtiPrincipal(org.dcache.auth.JwtJtiPrincipal) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) AuthenticationException(org.dcache.gplazma.AuthenticationException) List(java.util.List) Principal(java.security.Principal) Args(org.dcache.util.Args) Activity(org.dcache.auth.attributes.Activity) Optional(java.util.Optional) Collections(java.util.Collections) HttpClients(org.apache.http.impl.client.HttpClients) OidcSubjectPrincipal(org.dcache.auth.OidcSubjectPrincipal) JwtSubPrincipal(org.dcache.auth.JwtSubPrincipal) AuthenticationException(org.dcache.gplazma.AuthenticationException) ArrayList(java.util.ArrayList) BearerTokenCredential(org.dcache.auth.BearerTokenCredential) IOException(java.io.IOException) JsonWebToken(org.dcache.gplazma.util.JsonWebToken) MultiTargetedRestriction(org.dcache.auth.attributes.MultiTargetedRestriction) Restriction(org.dcache.auth.attributes.Restriction) ExemptFromNamespaceChecks(org.dcache.auth.ExemptFromNamespaceChecks) JwtJtiPrincipal(org.dcache.auth.JwtJtiPrincipal) JwtSubPrincipal(org.dcache.auth.JwtSubPrincipal) OpenIdGroupPrincipal(org.dcache.auth.OpenIdGroupPrincipal) OidcSubjectPrincipal(org.dcache.auth.OidcSubjectPrincipal) JwtJtiPrincipal(org.dcache.auth.JwtJtiPrincipal) Principal(java.security.Principal)

Example 3 with BearerTokenCredential

use of org.dcache.auth.BearerTokenCredential in project dcache by dCache.

the class GplazmaLoginSciTokenValidator method validate.

@Override
public void validate(ChannelHandlerContext ctx, String token) throws XrootdException {
    Subject tokenSubject = new Subject();
    tokenSubject.getPrivateCredentials().add(new BearerTokenCredential(token));
    LoginReply loginReply;
    try {
        LOGGER.debug("getting login reply with: {}.", tokenSubject.getPrivateCredentials());
        loginReply = loginStrategy.login(tokenSubject);
    } catch (PermissionDeniedCacheException e) {
        throw new XrootdException(kXR_NotAuthorized, e.toString());
    } catch (CacheException e) {
        throw new XrootdException(kXR_ServerError, e.toString());
    }
    /**
     *  It is possible the the user is already logged in via a standard
     *  authentication protocol.  In that case, the XrootdRedirectHandler
     *  in the door already has stored a Restriction object and user
     *  metadata.  This needs to be overwritten with the current values.
     */
    LOGGER.debug("notifying door of new login reply: {}.", loginReply);
    ctx.fireUserEventTriggered(new LoginEvent(loginReply));
}
Also used : PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) CacheException(diskCacheV111.util.CacheException) LoginReply(org.dcache.auth.LoginReply) LoginEvent(org.dcache.xrootd.door.LoginEvent) BearerTokenCredential(org.dcache.auth.BearerTokenCredential) XrootdException(org.dcache.xrootd.core.XrootdException) Subject(javax.security.auth.Subject)

Example 4 with BearerTokenCredential

use of org.dcache.auth.BearerTokenCredential in project dcache by dCache.

the class AuthenticationHandler method addAuthCredentialsToSubject.

private void addAuthCredentialsToSubject(HttpServletRequest request, Subject subject) throws PermissionDeniedCacheException {
    Optional<AuthInfo> optional = parseAuthenticationHeader(request);
    if (optional.isPresent()) {
        AuthInfo info = optional.get();
        switch(info.getScheme()) {
            case HttpServletRequest.BASIC_AUTH:
                if (!_isBasicAuthenticationEnabled) {
                    return;
                }
                try {
                    byte[] bytes = Base64.getDecoder().decode(info.getData().getBytes(StandardCharsets.US_ASCII));
                    String credential = new String(bytes, StandardCharsets.UTF_8);
                    int colon = credential.indexOf(":");
                    if (colon >= 0) {
                        String user = credential.substring(0, colon);
                        int lastHash = user.lastIndexOf('#');
                        if (lastHash != -1 && lastHash < (user.length() - 1)) {
                            Splitter.on(',').trimResults().omitEmptyStrings().split(user.substring(lastHash + 1)).forEach(r -> subject.getPrincipals().add(new DesiredRole(r)));
                            user = user.substring(0, lastHash);
                        }
                        String password = credential.substring(colon + 1);
                        subject.getPrivateCredentials().add(new PasswordCredential(user, password));
                    } else {
                        subject.getPrincipals().add(new LoginNamePrincipal(credential));
                    }
                } catch (IllegalArgumentException e) {
                    LOG.warn("Authentication Data in the header received is not Base64 encoded {}", request.getHeader("Authorization"));
                }
                break;
            case "BEARER":
                if (!_acceptBearerTokenUnencrypted && !request.isSecure()) {
                    throw new PermissionDeniedCacheException("not allowed to send bearer token unencrypted");
                }
                try {
                    subject.getPrivateCredentials().add(new BearerTokenCredential(info.getData()));
                } catch (IllegalArgumentException e) {
                    LOG.info("Bearer Token in invalid {}", request.getHeader("Authorization"));
                }
                break;
            default:
                LOG.debug("Unknown authentication scheme {}", info.getScheme());
        }
    }
}
Also used : PermissionDeniedCacheException(diskCacheV111.util.PermissionDeniedCacheException) PasswordCredential(org.dcache.auth.PasswordCredential) DesiredRole(org.dcache.auth.DesiredRole) BearerTokenCredential(org.dcache.auth.BearerTokenCredential) LoginNamePrincipal(org.dcache.auth.LoginNamePrincipal)

Example 5 with BearerTokenCredential

use of org.dcache.auth.BearerTokenCredential in project dcache by dCache.

the class OidcAuthPlugin method authenticate.

@Override
public void authenticate(Set<Object> publicCredentials, Set<Object> privateCredentials, Set<Principal> identifiedPrincipals, Set<Restriction> restrictions) throws AuthenticationException {
    String token = null;
    for (Object credential : privateCredentials) {
        if (credential instanceof BearerTokenCredential) {
            checkAuthentication(token == null, "Multiple bearer tokens");
            token = ((BearerTokenCredential) credential).getToken();
            LOG.debug("Found bearer token: {}", token);
        }
    }
    checkAuthentication(token != null, "No bearer token in the credentials");
    checkValid(token);
    try {
        ExtractResult result = tokenProcessor.extract(token);
        checkAuthentication(!result.claims().isEmpty(), "processing token yielded no claims");
        checkAudience(result.claims());
        var idp = result.idp();
        identifiedPrincipals.add(new OAuthProviderPrincipal(idp.getName()));
        Profile profile = idp.getProfile();
        var profileResult = profile.processClaims(idp, result.claims());
        identifiedPrincipals.addAll(profileResult.getPrincipals());
        profileResult.getRestriction().ifPresent(restrictions::add);
    } catch (UnableToProcess e) {
        throw new AuthenticationException("Unable to process token: " + e.getMessage());
    }
}
Also used : OAuthProviderPrincipal(org.dcache.auth.OAuthProviderPrincipal) AuthenticationException(org.dcache.gplazma.AuthenticationException) BearerTokenCredential(org.dcache.auth.BearerTokenCredential)

Aggregations

BearerTokenCredential (org.dcache.auth.BearerTokenCredential)5 PermissionDeniedCacheException (diskCacheV111.util.PermissionDeniedCacheException)3 CacheException (diskCacheV111.util.CacheException)2 Subject (javax.security.auth.Subject)2 AuthenticationException (org.dcache.gplazma.AuthenticationException)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Splitter (com.google.common.base.Splitter)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 FsPath (diskCacheV111.util.FsPath)1 IOException (java.io.IOException)1 Principal (java.security.Principal)1 Instant (java.time.Instant)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 EnumSet (java.util.EnumSet)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 Objects.requireNonNull (java.util.Objects.requireNonNull)1