Optimizing Imports and Formatting code
[ccsdk/cds.git] / ms / blueprintsprocessor / application / src / main / java / org / onap / ccsdk / cds / blueprintsprocessor / security / BasicAuthServerInterceptor.java
1 /*
2  * Copyright (C) 2019 Bell Canada.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onap.ccsdk.cds.blueprintsprocessor.security;
17
18 import com.google.common.base.Strings;
19 import io.grpc.*;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.security.authentication.BadCredentialsException;
24 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
25 import org.springframework.security.core.Authentication;
26 import org.springframework.security.core.AuthenticationException;
27 import org.springframework.security.core.context.SecurityContextHolder;
28 import org.springframework.stereotype.Component;
29
30 import java.nio.charset.StandardCharsets;
31 import java.util.Base64;
32
33 @Component
34 public class BasicAuthServerInterceptor implements ServerInterceptor {
35
36     private static Logger log = LoggerFactory.getLogger(BasicAuthServerInterceptor.class);
37
38     @Autowired
39     private AuthenticationManager authenticationManager;
40
41
42     @Override
43     public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
44         ServerCall<ReqT, RespT> call,
45         Metadata headers,
46         ServerCallHandler<ReqT, RespT> next) {
47         String authHeader = headers.get(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER));
48
49         if (Strings.isNullOrEmpty(authHeader)) {
50             throw Status.UNAUTHENTICATED.withDescription("Missing required authentication").asRuntimeException();
51
52         }
53
54         try {
55             String[] tokens = decodeBasicAuth(authHeader);
56             String username = tokens[0];
57
58             log.info("Basic Authentication Authorization header found for user: {}", username);
59
60             Authentication authRequest = new UsernamePasswordAuthenticationToken(username, tokens[1]);
61             Authentication authResult = authenticationManager.authenticate(authRequest).block();
62
63             log.info("Authentication success: {}", authResult);
64
65             SecurityContextHolder.getContext().setAuthentication(authResult);
66
67         } catch (AuthenticationException e) {
68             SecurityContextHolder.clearContext();
69
70             log.info("Authentication request failed: {}", e.getMessage());
71
72             throw Status.UNAUTHENTICATED.withDescription(e.getMessage()).withCause(e).asRuntimeException();
73         }
74
75         return next.startCall(call, headers);
76     }
77
78     private String[] decodeBasicAuth(String authHeader) {
79         String basicAuth;
80         try {
81             basicAuth = new String(Base64.getDecoder().decode(authHeader.substring(6).getBytes(StandardCharsets.UTF_8)),
82                 StandardCharsets.UTF_8);
83         } catch (IllegalArgumentException | IndexOutOfBoundsException e) {
84             throw new BadCredentialsException("Failed to decode basic authentication token");
85         }
86
87         int delim = basicAuth.indexOf(':');
88         if (delim == -1) {
89             throw new BadCredentialsException("Failed to decode basic authentication token");
90         }
91
92         return new String[]{basicAuth.substring(0, delim), basicAuth.substring(delim + 1)};
93     }
94 }