241b7c28e6a9ab80815b053ec92c5799884f2228
[moon.git] /
1 /*
2  * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.aaa.shiro.filters;
10
11 import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
12 import static javax.servlet.http.HttpServletResponse.SC_CREATED;
13 import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
14 import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
15
16 import java.io.IOException;
17 import java.io.PrintWriter;
18
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.oltu.oauth2.as.response.OAuthASResponse;
25 import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
26 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
27 import org.apache.oltu.oauth2.common.message.OAuthResponse;
28 import org.apache.oltu.oauth2.common.message.types.TokenType;
29 import org.apache.shiro.SecurityUtils;
30 import org.apache.shiro.authc.AuthenticationException;
31 import org.apache.shiro.authc.AuthenticationToken;
32 import org.apache.shiro.authc.UsernamePasswordToken;
33 import org.apache.shiro.subject.Subject;
34 import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
35 import org.opendaylight.aaa.AuthenticationBuilder;
36 import org.opendaylight.aaa.ClaimBuilder;
37 import org.opendaylight.aaa.api.Authentication;
38 import org.opendaylight.aaa.api.Claim;
39 import org.opendaylight.aaa.shiro.moon.MoonPrincipal;
40 import org.opendaylight.aaa.sts.OAuthRequest;
41 import org.opendaylight.aaa.sts.ServiceLocator;
42
43 /**
44  * MoonOAuthFilter filters oauth1 requests form token based authentication
45  * @author Alioune BA alioune.ba@orange.com
46  *
47  */
48 public class MoonOAuthFilter extends AuthenticatingFilter{
49
50     private static final String DOMAIN_SCOPE_REQUIRED = "Domain scope required";
51     private static final String NOT_IMPLEMENTED = "not_implemented";
52     private static final String UNAUTHORIZED = "unauthorized";
53     private static final String UNAUTHORIZED_CREDENTIALS = "Unauthorized: Login/Password incorrect";
54
55     static final String TOKEN_GRANT_ENDPOINT = "/token";
56     static final String TOKEN_REVOKE_ENDPOINT = "/revoke";
57     static final String TOKEN_VALIDATE_ENDPOINT = "/validate";
58
59     @Override
60     protected UsernamePasswordToken createToken(ServletRequest request, ServletResponse response) throws Exception {
61         // TODO Auto-generated method stub
62         HttpServletRequest httpRequest = (HttpServletRequest) request;
63         OAuthRequest oauthRequest = new OAuthRequest(httpRequest);
64         return new UsernamePasswordToken(oauthRequest.getUsername(),oauthRequest.getPassword());
65     }
66
67     @Override
68     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
69         // TODO Auto-generated method stub
70         Subject currentUser = SecurityUtils.getSubject();
71         return executeLogin(request, response);
72     }
73
74     protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
75             ServletRequest request, ServletResponse response) throws Exception {
76         HttpServletResponse httpResponse= (HttpServletResponse) response;
77         MoonPrincipal principal = (MoonPrincipal) subject.getPrincipals().getPrimaryPrincipal();
78         Claim claim = principal.principalToClaim();
79         oauthAccessTokenResponse(httpResponse,claim,"",principal.getToken());
80         return true;
81     }
82
83     protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
84             ServletRequest request, ServletResponse response) {
85         HttpServletResponse resp = (HttpServletResponse) response;
86         error(resp, SC_BAD_REQUEST, UNAUTHORIZED_CREDENTIALS);
87         return false;
88     }
89
90     protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
91
92         HttpServletRequest req= (HttpServletRequest) request;
93         HttpServletResponse resp = (HttpServletResponse) response;
94         try {
95             if (req.getServletPath().equals(TOKEN_GRANT_ENDPOINT)) {
96                 UsernamePasswordToken token = createToken(request, response);
97                 if (token == null) {
98                     String msg = "A valid non-null AuthenticationToken " +
99                             "must be created in order to execute a login attempt.";
100                     throw new IllegalStateException(msg);
101                 }
102                 try {
103                     Subject subject = getSubject(request, response);
104                     subject.login(token);
105                     return onLoginSuccess(token, subject, request, response);
106                 } catch (AuthenticationException e) {
107                     return onLoginFailure(token, e, request, response);
108                 }
109             } else if (req.getServletPath().equals(TOKEN_REVOKE_ENDPOINT)) {
110                 //TODO: deleteAccessToken(req, resp);
111             } else if (req.getServletPath().equals(TOKEN_VALIDATE_ENDPOINT)) {
112                 //TODO: validateToken(req, resp);
113             }
114         } catch (AuthenticationException e) {
115             error(resp, SC_UNAUTHORIZED, e.getMessage());
116         } catch (OAuthProblemException oe) {
117             error(resp, oe);
118         } catch (Exception e) {
119             error(resp, e);
120         }
121         return false;
122     }
123
124     private void oauthAccessTokenResponse(HttpServletResponse resp, Claim claim, String clientId, String token)
125             throws OAuthSystemException, IOException {
126         if (claim == null) {
127             throw new AuthenticationException(UNAUTHORIZED);
128         }
129
130         // Cache this token...
131         Authentication auth = new AuthenticationBuilder(new ClaimBuilder(claim).setClientId(
132                 clientId).build()).setExpiration(tokenExpiration()).build();
133         ServiceLocator.getInstance().getTokenStore().put(token, auth);
134
135         OAuthResponse r = OAuthASResponse.tokenResponse(SC_CREATED).setAccessToken(token)
136                                          .setTokenType(TokenType.BEARER.toString())
137                                          .setExpiresIn(Long.toString(auth.expiration()))
138                                          .buildJSONMessage();
139         write(resp, r);
140     }
141
142     private void write(HttpServletResponse resp, OAuthResponse r) throws IOException {
143         resp.setStatus(r.getResponseStatus());
144         PrintWriter pw = resp.getWriter();
145         pw.print(r.getBody());
146         pw.flush();
147         pw.close();
148     }
149
150     private long tokenExpiration() {
151         return ServiceLocator.getInstance().getTokenStore().tokenExpiration();
152     }
153
154     // Emit an error OAuthResponse with the given HTTP code
155     private void error(HttpServletResponse resp, int httpCode, String error) {
156         try {
157             OAuthResponse r = OAuthResponse.errorResponse(httpCode).setError(error)
158                                            .buildJSONMessage();
159             write(resp, r);
160         } catch (Exception e1) {
161             // Nothing to do here
162         }
163     }
164
165     private void error(HttpServletResponse resp, OAuthProblemException e) {
166         try {
167             OAuthResponse r = OAuthResponse.errorResponse(SC_BAD_REQUEST).error(e)
168                                            .buildJSONMessage();
169             write(resp, r);
170         } catch (Exception e1) {
171             // Nothing to do here
172         }
173     }
174
175     private void error(HttpServletResponse resp, Exception e) {
176         try {
177             OAuthResponse r = OAuthResponse.errorResponse(SC_INTERNAL_SERVER_ERROR)
178                                            .setError(e.getClass().getName())
179                                            .setErrorDescription(e.getMessage()).buildJSONMessage();
180             write(resp, r);
181         } catch (Exception e1) {
182             // Nothing to do here
183         }
184     }
185
186 }