org.joyrest.oauth2.BasicAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.joyrest.oauth2.BasicAuthenticator.java

Source

/*
 * Copyright 2015 Petr Bouda
 *
 * 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 org.joyrest.oauth2;

import java.io.IOException;

import org.joyrest.logging.JoyLogger;
import org.joyrest.model.request.InternalRequest;
import org.joyrest.model.request.Request;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import static java.util.Objects.isNull;

public class BasicAuthenticator {

    private static final JoyLogger logger = new JoyLogger(BasicAuthenticator.class);
    private static final String CREDENTIALS_CHARSET = "UTF-8";

    private final AuthenticationManager authenticationManager;

    public BasicAuthenticator(final AuthenticationManager oAuth2AuthenticationManager) {
        this.authenticationManager = oAuth2AuthenticationManager;
    }

    public Authentication authenticate(Request<?> request) {
        String header = request.getHeader("Authorization")
                .orElseThrow(() -> new BadCredentialsException("There is no Authorization header"));

        if (isNull(header) || !header.startsWith("Basic ")) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }

        try {
            String[] tokens = extractAndDecodeHeader(header);
            String username = tokens[0];

            logger.debug(() -> "Basic Authentication Authorization header found for user '" + username + "'");

            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
                    tokens[1]);

            Authentication authentication = authenticationManager.authenticate(authRequest);
            logger.debug(() -> "Authentication success: " + authentication);
            return authentication;
        } catch (IOException ex) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }
    }

    /**
     * Decodes the header into a username and password.
     *
     * @throws BadCredentialsException if the Basic header is not present or is not valid Base64
     */
    private String[] extractAndDecodeHeader(String header) throws IOException {

        byte[] base64Token = header.substring(6).getBytes(CREDENTIALS_CHARSET);
        byte[] decoded;
        try {
            decoded = Base64.decode(base64Token);
        } catch (IllegalArgumentException e) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }

        String token = new String(decoded, CREDENTIALS_CHARSET);

        int delim = token.indexOf(":");

        if (delim == -1) {
            throw new BadCredentialsException("Invalid basic authentication token");
        }
        return new String[] { token.substring(0, delim), token.substring(delim + 1) };
    }

}