6ac76c0a570cfa36c700d6fde74499d51610aee0
[moon.git] /
1 /*
2  * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. 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.federation;
10
11 import static javax.servlet.http.HttpServletResponse.SC_CREATED;
12 import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
13
14 import java.io.IOException;
15 import java.io.PrintWriter;
16 import java.util.List;
17 import javax.servlet.ServletConfig;
18 import javax.servlet.ServletException;
19 import javax.servlet.http.HttpServlet;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22 import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
23 import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
24 import org.apache.oltu.oauth2.as.issuer.UUIDValueGenerator;
25 import org.apache.oltu.oauth2.as.response.OAuthASResponse;
26 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
27 import org.apache.oltu.oauth2.common.message.OAuthResponse;
28 import org.opendaylight.aaa.AuthenticationBuilder;
29 import org.opendaylight.aaa.ClaimBuilder;
30 import org.opendaylight.aaa.api.Authentication;
31 import org.opendaylight.aaa.api.AuthenticationException;
32 import org.opendaylight.aaa.api.Claim;
33
34 /**
35  * An endpoint for claim-based authentication federation (in-bound).
36  *
37  * @author liemmn
38  *
39  */
40 public class FederationEndpoint extends HttpServlet {
41
42     private static final long serialVersionUID = -5553885846238987245L;
43
44     /** An in-bound authentication claim */
45     static final String AUTH_CLAIM = "AAA-CLAIM";
46
47     private static final String UNAUTHORIZED = "unauthorized";
48
49     private transient OAuthIssuer oi;
50
51     @Override
52     public void init(ServletConfig config) throws ServletException {
53         oi = new OAuthIssuerImpl(new UUIDValueGenerator());
54     }
55
56     @Override
57     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException,
58             ServletException {
59         try {
60             createRefreshToken(req, resp);
61         } catch (Exception e) {
62             error(resp, SC_UNAUTHORIZED, e.getMessage());
63         }
64     }
65
66     // Create a refresh token
67     private void createRefreshToken(HttpServletRequest req, HttpServletResponse resp)
68             throws OAuthSystemException, IOException {
69         Claim claim = (Claim) req.getAttribute(AUTH_CLAIM);
70         oauthRefreshTokenResponse(resp, claim);
71     }
72
73     // Build OAuth refresh token response from the given claim mapped and
74     // injected by the external IdP
75     private void oauthRefreshTokenResponse(HttpServletResponse resp, Claim claim)
76             throws OAuthSystemException, IOException {
77         if (claim == null) {
78             throw new AuthenticationException(UNAUTHORIZED);
79         }
80
81         String userName = claim.user();
82         // Need to have at least a mapped username!
83         if (userName == null) {
84             throw new AuthenticationException(UNAUTHORIZED);
85         }
86
87         String domain = claim.domain();
88         // Need to have at least a domain!
89         if (domain == null) {
90             throw new AuthenticationException(UNAUTHORIZED);
91         }
92
93         String userId = userName + "@" + domain;
94
95         // Create an unscoped ODL context from the external claim
96         Authentication auth = new AuthenticationBuilder(new ClaimBuilder(claim).setUserId(userId)
97                 .build()).setExpiration(tokenExpiration()).build();
98
99         // Create OAuth response
100         String token = oi.refreshToken();
101         OAuthResponse r = OAuthASResponse
102                 .tokenResponse(SC_CREATED)
103                 .setRefreshToken(token)
104                 .setExpiresIn(Long.toString(auth.expiration()))
105                 .setScope(
106                 // Use mapped domain if there is one, else list
107                 // all the ones that this user has access to
108                         (claim.domain().isEmpty()) ? listToString(ServiceLocator.getInstance()
109                                 .getIdmService().listDomains(userId)) : claim.domain())
110                 .buildJSONMessage();
111         // Cache this token...
112         ServiceLocator.getInstance().getTokenStore().put(token, auth);
113         write(resp, r);
114     }
115
116     // Token expiration
117     private long tokenExpiration() {
118         return ServiceLocator.getInstance().getTokenStore().tokenExpiration();
119     }
120
121     // Space-delimited string from a list of strings
122     private String listToString(List<String> list) {
123         StringBuffer sb = new StringBuffer();
124         for (String s : list) {
125             sb.append(s).append(" ");
126         }
127         return sb.toString().trim();
128     }
129
130     // Emit an error OAuthResponse with the given HTTP code
131     private void error(HttpServletResponse resp, int httpCode, String error) {
132         try {
133             OAuthResponse r = OAuthResponse.errorResponse(httpCode).setError(error)
134                     .buildJSONMessage();
135             write(resp, r);
136         } catch (Exception e1) {
137             // Nothing to do here
138         }
139     }
140
141     // Write out an OAuthResponse
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 }