comparison gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/Assertion.java @ 5940:05da3cfa4054

Add new SAML Assertion class based on WAS Assertion.
author Bernhard Herzog <bh@intevation.de>
date Wed, 08 May 2013 17:56:13 +0200
parents
children a51adfc957bf
comparison
equal deleted inserted replaced
5939:407cff3b03ab 5940:05da3cfa4054
1 /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
2 * Software engineering by Intevation GmbH
3 *
4 * This file is Free Software under the GNU AGPL (>=v3)
5 * and comes with ABSOLUTELY NO WARRANTY! Check out the
6 * documentation coming with Dive4Elements River for details.
7 */
8
9 package org.dive4elements.river.client.server.auth.saml;
10
11 import java.text.ParseException;
12 import java.text.SimpleDateFormat;
13 import java.util.Calendar;
14 import java.util.Date;
15 import java.util.List;
16 import java.util.LinkedList;
17 import java.util.TimeZone;
18 import javax.xml.namespace.QName;
19 import javax.xml.xpath.XPathConstants;
20
21 import org.apache.log4j.Logger;
22
23 import org.w3c.dom.Element;
24 import org.w3c.dom.NodeList;
25
26 /**
27 * Represents a SAML assertion about a user.
28 */
29 public class Assertion {
30
31 private static Logger logger = Logger.getLogger(Assertion.class);
32
33 private Element assertion;
34 private LinkedList<String> roles;
35 private String user_id;
36 private String name_id;
37 private String group_id;
38 private String group_name;
39 private Date notbefore;
40 private Date notonorafter;
41
42 private static final String ATTR_CONT_USER_ID =
43 "urn:conterra:names:sdi-suite:policy:attribute:user-id";
44 private static final String ATTR_CONT_GROUP_ID =
45 "urn:conterra:names:sdi-suite:policy:attribute:group-id";
46 private static final String ATTR_CONT_GROUP_NAME =
47 "urn:conterra:names:sdi-suite:policy:attribute:group-name";
48 private static final String ATTR_CONT_ROLE =
49 "urn:conterra:names:sdi-suite:policy:attribute:role";
50
51
52 public Assertion(Element assertion) {
53 this.assertion = assertion;
54 this.roles = new LinkedList<String>();
55 this.parseCondition();
56 this.parseAttributeStatement();
57 }
58
59 private void parseCondition() {
60 Element conditions = (Element)XPathUtils.xpathNode(this.assertion,
61 "saml:Conditions");
62 if (conditions == null) {
63 logger.error("Cannot find Assertion conditions element");
64 return;
65 }
66
67 this.notbefore = parseDateAttribute(conditions, "NotBefore");
68 if (this.notbefore == null) {
69 logger.warn("Could not extract NotBefore date.");
70 }
71 this.notonorafter = parseDateAttribute(conditions, "NotOnOrAfter");
72 if (this.notonorafter == null) {
73 logger.warn("Could not extract NotOnOrAfter date.");
74 }
75 }
76
77 private Date parseDateAttribute(Element element, String name) {
78 SimpleDateFormat dateformat = new SimpleDateFormat();
79 // format should be "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" but that's
80 // only available in java 7+. However, parsing without the
81 // time-zone yields Date values in the local time-zone,
82 // therefore we need to convert to GMT ourselves.
83 dateformat.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
84
85 String value = element.getAttribute(name);
86 try {
87 return toGMT(dateformat.parse(value));
88 }
89 catch(ParseException e) {
90 logger.error("Cannot parse Condition attribute "
91 + name + " with value " + value
92 + " (" + e.getLocalizedMessage() + ")");
93 }
94 return null;
95 }
96
97 private Date toGMT(Date date) {
98 Calendar cal = Calendar.getInstance();
99 cal.setTime(date);
100 cal.set(Calendar.ZONE_OFFSET, 0);
101 cal.set(Calendar.DST_OFFSET, 0);
102 return cal.getTime();
103 }
104
105 private void parseAttributeStatement() {
106 Element attrstatement = (Element)XPathUtils.xpathNode(this.assertion,
107 "saml:AttributeStatement");
108 if (attrstatement == null) {
109 logger.error("Cannot find Assertion AttributeStatement element");
110 return;
111 }
112
113 this.name_id = XPathUtils.xpathString(attrstatement,
114 "saml:Subject"
115 + "/saml:NameIdentifier");
116
117 this.user_id = getAttrValue(attrstatement, ATTR_CONT_USER_ID);
118 this.group_id = getAttrValue(attrstatement, ATTR_CONT_GROUP_ID);
119 this.group_name = getAttrValue(attrstatement, ATTR_CONT_GROUP_NAME);
120 this.roles = getAttrValues(attrstatement, ATTR_CONT_ROLE);
121 }
122
123 static Object getAttrObject(Element attrs, String name, QName returnType) {
124 return XPathUtils.xpath(attrs,
125 "saml:Attribute[@AttributeName='" + name + "']"
126 + "/saml:AttributeValue",
127 returnType);
128 }
129
130 static String getAttrValue(Element attrs, String name) {
131 return (String)getAttrObject(attrs, name, XPathConstants.STRING);
132 }
133
134 static LinkedList<String> getAttrValues(Element attrs, String name) {
135 LinkedList<String> strings = new LinkedList<String>();
136 NodeList nodes = (NodeList)getAttrObject(attrs, name,
137 XPathConstants.NODESET);
138 for (int i = 0; i < nodes.getLength(); i++) {
139 strings.add(nodes.item(i).getTextContent());
140 }
141
142 return strings;
143 }
144
145 public List<String> getRoles() {
146 return this.roles;
147 }
148
149 public String getUserID() {
150 return this.user_id;
151 }
152
153 public String getNameID() {
154 return this.name_id;
155 }
156
157 public String getGroupID() {
158 return this.group_id;
159 }
160
161 public String getGroupName() {
162 return this.group_name;
163 }
164
165 public Date getFrom() {
166 return this.notbefore;
167 }
168
169 public Date getUntil() {
170 return this.notonorafter;
171 }
172
173 /**
174 * Returns whether the ticket to which the assertion belongs is
175 * valid at the time the method is called. The method returns true,
176 * if both dates (notbefore and notonorafter) have been determined
177 * successfully and the current date/time is between both.
178 * @return Whether the ticket is valid now.
179 */
180 public boolean isValidNow() {
181 Date now = new Date();
182 return (this.notbefore != null && this.notonorafter != null
183 && now.after(this.notbefore)
184 && !this.notonorafter.before(now));
185 }
186 }
187 // vim: set fileencoding=utf-8 ts=4 sw=4 et si tw=80:

http://dive4elements.wald.intevation.org