2 * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.aaa.shiro.filters;
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;
16 import java.io.IOException;
17 import java.io.PrintWriter;
19 import javax.servlet.ServletRequest;
20 import javax.servlet.ServletResponse;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
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;
44 * MoonOAuthFilter filters oauth1 requests form token based authentication
45 * @author Alioune BA alioune.ba@orange.com
48 public class MoonOAuthFilter extends AuthenticatingFilter{
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";
55 static final String TOKEN_GRANT_ENDPOINT = "/token";
56 static final String TOKEN_REVOKE_ENDPOINT = "/revoke";
57 static final String TOKEN_VALIDATE_ENDPOINT = "/validate";
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());
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);
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());
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);
90 protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
92 HttpServletRequest req= (HttpServletRequest) request;
93 HttpServletResponse resp = (HttpServletResponse) response;
95 if (req.getServletPath().equals(TOKEN_GRANT_ENDPOINT)) {
96 UsernamePasswordToken token = createToken(request, response);
98 String msg = "A valid non-null AuthenticationToken " +
99 "must be created in order to execute a login attempt.";
100 throw new IllegalStateException(msg);
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);
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);
114 } catch (AuthenticationException e) {
115 error(resp, SC_UNAUTHORIZED, e.getMessage());
116 } catch (OAuthProblemException oe) {
118 } catch (Exception e) {
124 private void oauthAccessTokenResponse(HttpServletResponse resp, Claim claim, String clientId, String token)
125 throws OAuthSystemException, IOException {
127 throw new AuthenticationException(UNAUTHORIZED);
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);
135 OAuthResponse r = OAuthASResponse.tokenResponse(SC_CREATED).setAccessToken(token)
136 .setTokenType(TokenType.BEARER.toString())
137 .setExpiresIn(Long.toString(auth.expiration()))
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());
150 private long tokenExpiration() {
151 return ServiceLocator.getInstance().getTokenStore().tokenExpiration();
154 // Emit an error OAuthResponse with the given HTTP code
155 private void error(HttpServletResponse resp, int httpCode, String error) {
157 OAuthResponse r = OAuthResponse.errorResponse(httpCode).setError(error)
160 } catch (Exception e1) {
161 // Nothing to do here
165 private void error(HttpServletResponse resp, OAuthProblemException e) {
167 OAuthResponse r = OAuthResponse.errorResponse(SC_BAD_REQUEST).error(e)
170 } catch (Exception e1) {
171 // Nothing to do here
175 private void error(HttpServletResponse resp, Exception e) {
177 OAuthResponse r = OAuthResponse.errorResponse(SC_INTERNAL_SERVER_ERROR)
178 .setError(e.getClass().getName())
179 .setErrorDescription(e.getMessage()).buildJSONMessage();
181 } catch (Exception e1) {
182 // Nothing to do here