2 * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package edu.internet2.middleware.shibboleth.wayf;
19 import java.util.ArrayList;
20 import java.util.Iterator;
22 import javax.servlet.http.Cookie;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
26 import org.bouncycastle.util.encoders.Base64;
29 * Implementation of the <code>_saml_idp </code> cookie.
31 * Note that any SamlIdPCookie is only valid for as long as the reqest/response
32 * parameters provided to getIdPCookie remain valid.
34 * @author Rod Widdowson
37 public class SamlIdPCookie {
39 private static final String COOKIE_NAME = "_saml_idp";
41 private final HttpServletRequest req;
42 private final HttpServletResponse res;
43 private final String domain;
44 private final ArrayList /*<String>*/ idPList = new ArrayList/*<String>*/();
47 * Constructs a <code>SamlIdPCookie</code> from the provided string (which is the raw data
50 * the information read from the cookie
51 * @param domain - if non null the domain for any *created* cookie.
53 private SamlIdPCookie(String codedData, HttpServletRequest req, HttpServletResponse res, String domain) {
62 if (codedData == null || codedData.equals("")) {
66 // Because there are spaces in the data the cookie may be returned enclosed in quotes
68 if (codedData.charAt(0) == '"' && codedData.charAt(codedData.length()-1) == '"') {
69 codedData= codedData.substring(1,codedData.length()-1);
74 end = codedData.indexOf(' ', start);
76 String value = codedData.substring(start, end);
78 end = codedData.indexOf(' ', start);
79 if (!value.equals("")) {
80 idPList.add(new String(Base64.decode(value)));
83 if (start < codedData.length()) {
84 String value = codedData.substring(start);
85 if (!value.equals("")) {
86 idPList.add(new String(Base64.decode(value)));
91 * Create a SamlCookie with no data inside.
92 * @param domain - if non null, the domain of the new cookie
95 public SamlIdPCookie(HttpServletRequest req, HttpServletResponse res, String domain) {
102 * Add the specified Shibboleth IdP Name to the cookie list or move to
103 * the front and then write it back.
105 * We always add to the front (and remove from wherever it was)
107 * @param idPName - The name to be added
108 * @param expiration - The expiration of the cookie or zero if it is to be unchanged
110 public void addIdPName(String idPName, int expiration) {
112 idPList.remove(idPName);
113 idPList.add(0, idPName);
115 writeCookie(expiration);
119 * Return an iterator over the list of IdPNames
124 public Iterator/*<String>*/ iterator() {
126 return idPList.iterator();
130 * Delete the <b>entire<\b> cookie contents
133 public static void deleteCookie(HttpServletRequest req, HttpServletResponse res) {
134 Cookie cookie = getCookie(req);
136 if (cookie == null) {
140 res.addCookie(cookie);
144 * Load up the cookie and convert it into a SamlIdPCookie. If there is no
145 * underlying cookie return a null one.
146 * @param domain - if this is set then any <b>created</b> cookies are set to this domain
149 public static SamlIdPCookie getIdPCookie(HttpServletRequest req, HttpServletResponse res, String domain) {
150 Cookie cookie = getCookie(req);
152 if (cookie == null) {
153 return new SamlIdPCookie(req, res, domain);
155 return new SamlIdPCookie(cookie.getValue(), req, res, domain);
160 * Remove origin from the cachedata and write it back.
164 public void deleteIdPName(String origin) {
165 idPList.remove(origin);
169 private void writeCookie(int expiration)
171 Cookie cookie = getCookie(req);
173 if (idPList.size() == 0) {
175 // Nothing to write, so delete the cookie
178 res.addCookie(cookie);
183 // Otherwise encode up the cookie
186 StringBuffer buffer = new StringBuffer();
187 Iterator /*<String>*/ it = idPList.iterator();
189 while (it.hasNext()) {
190 String next = (String) it.next();
191 String what = new String(Base64.encode(next.getBytes()));
192 buffer.append(what).append(' ');
195 String value = buffer.toString();
197 if (cookie == null) {
198 cookie = new Cookie(COOKIE_NAME, value);
200 cookie.setValue(value);
202 cookie.setComment("Used to cache selection of a user's Shibboleth IdP");
205 if (expiration > 0) {
206 cookie.setMaxAge(expiration);
208 if (domain != null && domain != "") {
209 cookie.setDomain(domain);
211 res.addCookie(cookie);
215 private static Cookie getCookie(HttpServletRequest req) {
217 Cookie[] cookies = req.getCookies();
218 if (cookies != null) {
219 for (int i = 0; i < cookies.length; i++) {
220 if (cookies[i].getName().equals(COOKIE_NAME)) {