comparison src/main/java/de/intevation/lada/util/auth/OpenIDAuthentication.java @ 544:04e254571b8a openid

First non-functional implementation of openid verification Uses the openid4j package to extract openid information provided by the client as a HTTP Header. Currently the statelessness of the services prevents the exchange of discovery information between client and server. It is only useful for evaluation and testing.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 25 Feb 2015 16:03:35 +0100
parents
children
comparison
equal deleted inserted replaced
532:56a2d43b4af5 544:04e254571b8a
1 /* Copyright (C) 2015 by Bundesamt fuer Strahlenschutz
2 * Software engineering by Intevation GmbH
3 *
4 * This file is Free Software under the GNU GPL (v>=3)
5 * and comes with ABSOLUTELY NO WARRANTY! Check out
6 * the documentation coming with IMIS-Labordaten-Application for details.
7 */
8 package de.intevation.lada.util.auth;
9
10 import java.util.Map;
11 import java.util.List;
12 import java.util.LinkedHashMap;
13 import java.net.URLDecoder;
14
15 import javax.inject.Inject;
16 import javax.ejb.Stateless;
17 import javax.ws.rs.core.HttpHeaders;
18
19 import de.intevation.lada.util.annotation.AuthenticationConfig;
20
21 import org.openid4java.association.AssociationSessionType;
22 import org.openid4java.association.AssociationException;
23 import org.openid4java.consumer.ConsumerManager;
24 import org.openid4java.consumer.ConsumerException;
25 import org.openid4java.consumer.InMemoryConsumerAssociationStore;
26 import org.openid4java.consumer.InMemoryNonceVerifier;
27 import org.openid4java.message.ParameterList;
28 import org.openid4java.consumer.VerificationResult;
29 import org.openid4java.discovery.DiscoveryInformation;
30 import org.openid4java.discovery.Identifier;
31 import org.openid4java.discovery.DiscoveryException;
32 import org.openid4java.message.MessageException;
33 import org.openid4java.message.AuthRequest;
34
35 import org.apache.log4j.Logger;
36
37 public class OpenIDAuthentication implements Authentication {
38
39 /** The name of the header field used to transport OpenID parameters.*/
40 private static final String OID_HEADER_FIELD= "X-OPENID-PARAMS";
41
42 /** The identity provider we accept here. */
43 private static final String IDENTITY_PROVIDER =
44 "http://localhost:8087/account";
45
46 /** This is currently a faked dummy */
47 private static final String RETURN_URL =
48 "http://localhost:8086/consumer-servlet/consumer?is_return=true";
49
50 private static final Logger logger =
51 Logger.getLogger(OpenIDAuthentication.class);
52
53 private ConsumerManager manager;
54
55 private Map<String,String> idParams;
56
57 boolean discoveryDone = false;
58
59 private DiscoveryInformation discovered;
60
61 private boolean discoverServer() {
62 /* Perform discovery on the configured IDENTITY_PROVIDER */
63 List discoveries = null;
64 try {
65 discoveries = manager.discover(IDENTITY_PROVIDER);
66 } catch (DiscoveryException e) {
67 logger.debug("Discovery failed: " + e.getMessage());
68 return false;
69 }
70
71 if (discoveries == null || discoveries.isEmpty()) {
72 logger.error(
73 "Failed discovery step. OpenID provider unavailable?");
74 return false;
75 }
76
77 /* Add association for the discovered information */
78 discovered = manager.associate(discoveries);
79
80 /* Validate the parameters. */
81 logger.debug("After discovery.");
82 try {
83 AuthRequest authReq = manager.authenticate(discovered, RETURN_URL);
84 logger.debug("Authenticate with: " + authReq.getDestinationUrl(true));
85 } catch (MessageException e) {
86 logger.debug("Failed to create the Authentication request: " +
87 e.getMessage());
88 } catch (ConsumerException e) {
89 logger.debug("Error in consumer manager: " +
90 e.getMessage());
91 }
92 logger.debug("After authenticate.");
93 return true;
94 }
95
96 public OpenIDAuthentication() {
97 manager = new ConsumerManager();
98 /* TODO: Check for alternative configs. */
99 manager.setAssociations(new InMemoryConsumerAssociationStore());
100 manager.setNonceVerifier(new InMemoryNonceVerifier(50000));
101 manager.setMinAssocSessEnc(AssociationSessionType.DH_SHA256);
102 discoveryDone = discoverServer();
103 }
104
105 /** Split up the OpenID response query provided in the header.
106 *
107 * @param responseQuery The query provided in the header field.
108 * @return The query as ParameterList or null on error.
109 */
110 private ParameterList splitParams(String responseQuery) {
111 Map<String, String> queryMap =
112 new LinkedHashMap<String, String>();
113 final String[] pairs = responseQuery.split("&");
114 for (String pair : pairs) {
115 final int idx = pair.indexOf("=");
116 if (idx <= 0) {
117 logger.debug("Invalid query.");
118 return null;
119 }
120 try {
121 final String key = URLDecoder.decode(
122 pair.substring(0, idx), "UTF-8");
123
124 if (queryMap.containsKey(key)) {
125 logger.debug("Invalid query. Duplicate key: " + key);
126 return null;
127 }
128 final String value = URLDecoder.decode(
129 pair.substring(idx + 1), "UTF-8");
130 queryMap.put(key, value);
131 } catch (java.io.UnsupportedEncodingException e) {
132 logger.error("UTF-8 unkown?!");
133 return null;
134 }
135 }
136 if (queryMap.isEmpty()) {
137 logger.debug("Empty query.");
138 return null;
139 }
140 return new ParameterList(queryMap);
141 }
142
143 private boolean checkOpenIDHeader(HttpHeaders headers) {
144 /* First check if there are is anything provided */
145 List<String> oidParamString = headers.getRequestHeader(
146 OID_HEADER_FIELD);
147 if (oidParamString == null) {
148 logger.debug("Header " + OID_HEADER_FIELD + " not provided.");
149 return false;
150 }
151 if (oidParamString.size() != 1) {
152 logger.debug("Found " + oidParamString.size() + " openid headers.");
153 return false;
154 }
155
156 /* Parse the parameters. Do it first to avoid a useless discovery. */
157 ParameterList oidParams = splitParams(oidParamString.get(0));
158 if (oidParams == null) {
159 return false;
160 }
161
162 VerificationResult verification = null;
163 try {
164 verification = manager.verify(RETURN_URL, oidParams, discovered);
165 } catch (MessageException e) {
166 logger.debug("Verification failed: " + e.getMessage());
167 return false;
168 } catch (DiscoveryException e) {
169 logger.debug("Verification discovery exception: " + e.getMessage());
170 return false;
171 } catch (AssociationException e) {
172 logger.debug("Verification assoc exception: " + e.getMessage());
173 return false;
174 }
175
176
177 /* See what could be verified */
178 Identifier verified = verification.getVerifiedId();
179 if (verified == null) {
180 logger.debug("Failed to verify Identity information: " +
181 verification.getStatusMsg());
182 return false;
183 }
184
185 logger.debug("Verified user: " + verified);
186
187 return true;
188 }
189
190 @Override
191 public boolean isAuthenticated(HttpHeaders headers) {
192 if (!discoveryDone) {
193 discoveryDone = discoverServer();
194 }
195 if (!discoveryDone) {
196 return false;
197 }
198 if (checkOpenIDHeader(headers)) {
199 /** Successfully authenticated. */
200 return true;
201 } else {
202
203 return false;
204 }
205 }
206 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)