2  * ============LICENSE_START=======================================================
 
   3  * ONAP : ccsdk features
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
 
   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
 
  12  *     http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  22 package org.onap.ccsdk.features.sdnr.wt.oauthprovider;
 
  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.opendaylight.aaa.shiro.filters.backport.BearerToken;
 
  38 import org.opendaylight.aaa.shiro.realm.TokenAuthRealm;
 
  39 import org.slf4j.Logger;
 
  40 import org.slf4j.LoggerFactory;
 
  42 public class OAuth2Realm extends TokenAuthRealm {
 
  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;
 
  49     public OAuth2Realm() throws IOException {
 
  51         super.setName(REALM_NAME);
 
  52         this.config = Config.getInstance();
 
  53         this.tokenCreator = TokenCreator.getInstance(this.config);
 
  54         LOG.info("instantiated");
 
  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);
 
  66     public String getName() {
 
  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");
 
  78         } else if (this.config.doSupportOdlUsers() && (atoken instanceof UsernamePasswordToken)) {
 
  81             throw new AuthenticationException("AuthenticationInfo is not an OAuth2AuthenticationInfo");
 
  86     // check what I can do
 
  88     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg) {
 
  90         LOG.debug("auth info in shiro");
 
  91         Object principal = arg.getPrimaryPrincipal();
 
  92         if (principal instanceof DecodedJWT) {
 
  93             LOG.debug("detected jwt token");
 
  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);
 
 102                 return authorizationInfo;
 
 103             } catch (ClassCastException e) {
 
 104                 LOG.error("Couldn't decode authorization request", e);
 
 106         } else if (principal instanceof ODLPrincipal) {
 
 107             LOG.debug("detected basic token");
 
 108             ODLPrincipal odlPrincipal = (ODLPrincipal) principal;
 
 109             return new SimpleAuthorizationInfo(odlPrincipal.getRoles());
 
 111         return new SimpleAuthorizationInfo();
 
 118     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
 
 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;
 
 128             DecodedJWT jwt = this.tokenCreator.verify(oauthToken.getToken());
 
 130                 SimpleAuthenticationInfo authenticationInfo =
 
 131                         new SimpleAuthenticationInfo(jwt, token.getCredentials(), getName());
 
 132                 return authenticationInfo;
 
 136             LOG.debug("no valid token found");
 
 138         throw new AuthenticationException("unable to verify token " + token);