Mercurial > lada > lada-server
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 } |