Create method of Logging to O/S from Container
[aaf/authz.git] / auth / auth-oauth / src / main / java / org / onap / aaf / auth / oauth / DirectOAuthTAF.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.auth.oauth;
23
24 import java.io.IOException;
25 import java.security.GeneralSecurityException;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.Map;
28
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.onap.aaf.auth.dao.hl.Question;
33 import org.onap.aaf.auth.direct.DirectAAFUserPass;
34 import org.onap.aaf.auth.env.AuthzEnv;
35 import org.onap.aaf.auth.env.AuthzTrans;
36 import org.onap.aaf.auth.layer.Result;
37 import org.onap.aaf.auth.oauth.facade.DirectIntrospect;
38 import org.onap.aaf.auth.rserv.TransFilter;
39 import org.onap.aaf.cadi.CachedPrincipal;
40 import org.onap.aaf.cadi.CachedPrincipal.Resp;
41 import org.onap.aaf.cadi.CadiException;
42 import org.onap.aaf.cadi.CredVal.Type;
43 import org.onap.aaf.cadi.Hash;
44 import org.onap.aaf.cadi.LocatorException;
45 import org.onap.aaf.cadi.PropAccess;
46 import org.onap.aaf.cadi.Taf.LifeForm;
47 import org.onap.aaf.cadi.config.Config;
48 import org.onap.aaf.cadi.oauth.OAuth2HttpTafResp;
49 import org.onap.aaf.cadi.oauth.OAuth2Principal;
50 import org.onap.aaf.cadi.oauth.TokenClient;
51 import org.onap.aaf.cadi.oauth.TokenClientFactory;
52 import org.onap.aaf.cadi.oauth.TokenMgr;
53 import org.onap.aaf.cadi.oauth.TokenMgr.TokenPermLoader;
54 import org.onap.aaf.cadi.oauth.TokenPerm;
55 import org.onap.aaf.cadi.principal.OAuth2FormPrincipal;
56 import org.onap.aaf.cadi.taf.HttpTaf;
57 import org.onap.aaf.cadi.taf.TafResp;
58 import org.onap.aaf.cadi.taf.TafResp.RESP;
59 import org.onap.aaf.cadi.util.Split;
60 import org.onap.aaf.misc.env.APIException;
61
62 import aafoauth.v2_0.Introspect;
63
64 public class DirectOAuthTAF implements HttpTaf {
65         private PropAccess access;
66         private DirectIntrospect<Introspect> oaFacade;
67         private TokenMgr tkMgr;
68         private final DirectAAFUserPass directUserPass;
69         private TokenClient altIntrospectClient;
70
71         public DirectOAuthTAF(AuthzEnv env, Question q,  DirectIntrospect<Introspect> facade) throws APIException, CadiException {
72                 access = env.access();
73                 oaFacade = facade;
74                 tkMgr = TokenMgr.getInstance(access,"dbToken","dbIntrospect");
75                 String alt_url = access.getProperty(Config.AAF_ALT_OAUTH2_INTROSPECT_URL,null);
76                 TokenClientFactory tcf;
77                 if(alt_url!=null) {
78                         try {
79                                 tcf = TokenClientFactory.instance(access);
80                                 String[] split = Split.split(',', alt_url);
81                                 int timeout = split.length>1?Integer.parseInt(split[1]):3000;
82                                 altIntrospectClient = tcf.newClient(split[0], timeout);
83                                 altIntrospectClient.client_creds(access.getProperty(Config.AAF_ALT_CLIENT_ID,null), 
84                                                                                    access.getProperty(Config.AAF_ALT_CLIENT_SECRET,null));
85                         } catch (GeneralSecurityException | IOException | LocatorException e) {
86                                 throw new CadiException(e);
87                         }
88                 }
89
90                 directUserPass = new DirectAAFUserPass(env,q);
91         }
92
93         @Override
94         public TafResp validate(LifeForm reading, HttpServletRequest req, HttpServletResponse resp) {
95                 String value;
96                 String token;
97                 if((value=req.getHeader("Authorization"))!=null && value.startsWith("Bearer ")) {
98                         token = value.substring(7);
99                 } else {
100                         token = null;
101                 }
102
103                 if("application/x-www-form-urlencoded".equals(req.getContentType())) {
104                         @SuppressWarnings("unchecked")
105                         Map<String, String[]> map = req.getParameterMap();
106                         String client_id=null,client_secret=null,username=null,password=null;
107                         for(Map.Entry<String, String[]> es : map.entrySet()) {
108                                 switch(es.getKey()) {
109                                         case "client_id":
110                                                 for(String s : es.getValue()) {
111                                                         client_id=s;
112                                                 }
113                                                 break;
114                                         case "client_secret":
115                                                 for(String s : es.getValue()) {
116                                                         client_secret=s;
117                                                 }
118                                                 break;
119                                         case "username":
120                                                 for(String s : es.getValue()) {
121                                                         username=s;
122                                                 }
123                                                 break;
124                                         case "password":
125                                                 for(String s : es.getValue()) {
126                                                         password=s;
127                                                 }
128                                                 break;
129                                         case "token": 
130                                                 if(token!=null) { // Defined as both Bearer and Form Encoded - Error
131                                                         return new OAuth2HttpTafResp(access, null, "Token Info found as both Bearer Token and Form Info", RESP.FAIL, resp, true);
132                                                 }
133                                                 for(String s : es.getValue()) {
134                                                         token=s;
135                                                 }
136                                                 break;
137                                         // Ignore others
138                                 }
139                         }
140                         
141                         if(client_id==null || client_secret==null) {
142                                 return new OAuth2HttpTafResp(access, null, "client_id and client_secret required", RESP.TRY_ANOTHER_TAF, resp, false);
143                         }
144                         
145                         if(token==null) { // No Token to work with, use only Client_ID and Client_Secret 
146                                 AuthzTrans trans = (AuthzTrans)req.getAttribute(TransFilter.TRANS_TAG);
147
148                                 if(directUserPass.validate(client_id, Type.PASSWORD, client_secret.getBytes(), trans)) {
149                                         // Client_ID is valid
150                                         if(username==null) { // Validating just the Client_ID
151                                                 return new OAuth2FormHttpTafResp(access,new OAuth2FormPrincipal(client_id,client_id),"OAuth client_id authenticated",RESP.IS_AUTHENTICATED,resp,false);
152                                         } else {
153                                                 //TODO - Does a clientID need specific Authorization to pair authentication with user name?  At the moment, no.
154                                                 // username is ok.
155                                                 if(password!=null) {
156                                                         if(directUserPass.validate(username, Type.PASSWORD, password.getBytes(), trans)) {
157                                                                 return new OAuth2FormHttpTafResp(access,new OAuth2FormPrincipal(client_id, username),"OAuth username authenticated",RESP.IS_AUTHENTICATED,resp,false);
158                                                         } else {
159                                                                 return new OAuth2HttpTafResp(access,null,"OAuth username " + username + " not authenticated ",RESP.FAIL,resp,true);
160                                                         }
161                                                 } else { // no Password
162                                                         //TODO Check for Trust Permission, which requires looking up Perms?
163                                                         return new OAuth2HttpTafResp(access,null,"OAuth username " + username + " not authenticated ",RESP.FAIL,resp,true);
164                                                 }
165                                         }
166                                 } else {
167                                         return new OAuth2HttpTafResp(access,null,"OAuth client_id " + client_id + " not authenticated ",RESP.FAIL,resp,true);
168                                 }
169                         }
170                 } 
171                 
172                 // OK, have only a Token to validate
173                 if(token!=null) {
174                         AuthzTrans trans = (AuthzTrans)req.getAttribute(TransFilter.TRANS_TAG);
175
176                         try {
177                                 Result<Introspect> ri = oaFacade.mappedIntrospect(trans, token);
178                                 if(ri.isOK()) {
179                                         TokenPerm tp = tkMgr.putIntrospect(ri.value, Hash.hashSHA256(token.getBytes()));
180                                         if(tp==null) {
181                                                 return new OAuth2HttpTafResp(access, null, "TokenPerm persistence failure", RESP.FAIL, resp, false);
182                                         } else {
183                                                 return new OAuth2HttpTafResp(access,new OAuth2Principal(tp,Hash.hashSHA256(token.getBytes())),"Token Authenticated",RESP.IS_AUTHENTICATED,resp,false);
184                                         }
185                                 } else {
186                                         return new OAuth2HttpTafResp(access, null, ri.errorString(), RESP.FAIL, resp, false);
187                                 }
188                         } catch (APIException e) {
189                                 trans.error().log(e,"Error getting token");
190                                 return new OAuth2HttpTafResp(access, null, "Error getting token: " + e.getMessage(), RESP.TRY_ANOTHER_TAF, resp, false);
191                         } catch (NoSuchAlgorithmException e) {
192                                 return new OAuth2HttpTafResp(access, null, "Error in security algorithm: " + e.getMessage(), RESP.TRY_ANOTHER_TAF, resp, false);
193                         }
194                 }
195                 return new OAuth2HttpTafResp(access, null, "No OAuth2 Credentials in OAuthForm", RESP.TRY_ANOTHER_TAF, resp, false);
196         }
197
198         @Override
199         public Resp revalidate(CachedPrincipal prin, Object state) {
200                 // TODO Auto-generated method stub
201                 return null;
202         }
203
204         class ServiceTPL implements TokenPermLoader {
205                 private final AuthzTrans trans;
206                 public ServiceTPL(AuthzTrans atrans) {
207                         trans = atrans;
208                 }
209                 
210                 @Override
211                 public org.onap.aaf.cadi.client.Result<TokenPerm> load(String accessToken, byte[] cred) throws APIException, CadiException, LocatorException {
212                         Result<Introspect> ri = oaFacade.mappedIntrospect(trans, accessToken);
213                         if(ri.notOK()) {
214                                 //TODO what should the status mapping be?
215                                 return org.onap.aaf.cadi.client.Result.err(ri.status,ri.errorString());
216                         }
217                         return org.onap.aaf.cadi.client.Result.ok(200,tkMgr.putIntrospect(ri.value, cred));
218                 }
219         }
220
221         public DirectAAFUserPass directUserPass() {
222                 return directUserPass;
223         }
224 }
225