6dbed1f850a82b6fa53b22a810e2392956d84c37
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.oauthprovider;
23
24 import com.auth0.jwt.interfaces.DecodedJWT;
25 import java.io.IOException;
26 import org.apache.shiro.authc.AuthenticationException;
27 import org.apache.shiro.authc.AuthenticationInfo;
28 import org.apache.shiro.authc.AuthenticationToken;
29 import org.apache.shiro.authc.SimpleAuthenticationInfo;
30 import org.apache.shiro.authc.UsernamePasswordToken;
31 import org.apache.shiro.authz.AuthorizationInfo;
32 import org.apache.shiro.authz.SimpleAuthorizationInfo;
33 import org.apache.shiro.subject.PrincipalCollection;
34 import org.onap.ccsdk.features.sdnr.wt.oauthprovider.data.Config;
35 import org.onap.ccsdk.features.sdnr.wt.oauthprovider.providers.TokenCreator;
36 import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
37 import org.apache.shiro.authc.BearerToken;
38 import org.opendaylight.aaa.shiro.realm.TokenAuthRealm;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class OAuth2Realm extends TokenAuthRealm {
43
44     public static final String REALM_NAME = "OAuth2Realm";
45     private static final Logger LOG = LoggerFactory.getLogger(OAuth2Realm.class);
46     private final TokenCreator tokenCreator;
47     private final Config config;
48
49     public OAuth2Realm() throws IOException {
50         super();
51         super.setName(REALM_NAME);
52         this.config = Config.getInstance();
53         this.tokenCreator = TokenCreator.getInstance(this.config);
54         LOG.info("instantiated");
55     }
56
57     @Override
58     public boolean supports(AuthenticationToken token) {
59         boolean supports = (token instanceof BearerToken)
60                 || (this.config.doSupportOdlUsers() && (token instanceof UsernamePasswordToken));
61         LOG.debug("supports {} is {}", token == null ? null : token.getClass().getName(), supports);
62         return supports;
63     }
64
65     @Override
66     public String getName() {
67         return REALM_NAME;
68     }
69
70     @Override
71     protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)
72             throws AuthenticationException {
73         LOG.debug("assertCredentialsMatch");
74         if (atoken instanceof BearerToken) {
75             if (this.tokenCreator.verify(((BearerToken) atoken).getToken()) == null) {
76                 throw new AuthenticationException("Credentials do not match");
77             }
78         } else if (this.config.doSupportOdlUsers() && (atoken instanceof UsernamePasswordToken)) {
79             //nothing to do
80         } else {
81             throw new AuthenticationException("AuthenticationInfo is not an OAuth2AuthenticationInfo");
82         }
83     }
84
85
86     // check what I can do
87     @Override
88     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) {
89
90         LOG.debug("auth info in shiro");
91         Object principal = arg.getPrimaryPrincipal();
92         if (principal instanceof DecodedJWT) {
93             LOG.debug("detected jwt token");
94             try {
95                 DecodedJWT token = (DecodedJWT) arg.getPrimaryPrincipal();
96                 String[] roles = token.getClaim("roles").asArray(String.class);
97                 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
98                 for (String role : roles) {
99                     LOG.trace("found role {} in token", role);
100                     authorizationInfo.addRole(role);
101                 }
102                 return authorizationInfo;
103             } catch (ClassCastException e) {
104                 LOG.error("Couldn't decode authorization request", e);
105             }
106         } else if (principal instanceof ODLPrincipal) {
107             LOG.debug("detected basic token");
108             ODLPrincipal odlPrincipal = (ODLPrincipal) principal;
109             return new SimpleAuthorizationInfo(odlPrincipal.getRoles());
110         }
111         return new SimpleAuthorizationInfo();
112     }
113
114
115
116     // check who I am
117     @Override
118     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
119
120         LOG.debug("auth token in shiro:");
121         if (token instanceof UsernamePasswordToken && this.config.doSupportOdlUsers()) {
122             LOG.debug("basic auth token found");
123             return super.doGetAuthenticationInfo(token);
124         } else if (token instanceof BearerToken) {
125             LOG.debug("jwt token found");
126             BearerToken oauthToken = (BearerToken) token;
127
128             DecodedJWT jwt = this.tokenCreator.verify(oauthToken.getToken());
129             if (jwt != null) {
130                 SimpleAuthenticationInfo authenticationInfo =
131                         new SimpleAuthenticationInfo(jwt, token.getCredentials(), getName());
132                 return authenticationInfo;
133
134             }
135         } else {
136             LOG.debug("no valid token found");
137         }
138         throw new AuthenticationException("unable to verify token " + token);
139
140     }
141
142 }