View Javadoc

1   /*
2    * Copyright 2007 University Corporation for Advanced Internet Development, Inc.
3    *
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
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
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.
15   */
16  
17  package edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.attributeDefinition;
18  
19  import java.security.NoSuchAlgorithmException;
20  
21  import org.opensaml.common.IdentifierGenerator;
22  import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
23  import org.opensaml.util.storage.StorageService;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
28  import edu.internet2.middleware.shibboleth.common.attribute.provider.BasicAttribute;
29  import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolutionException;
30  import edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.ShibbolethResolutionContext;
31  import edu.internet2.middleware.shibboleth.common.profile.provider.SAMLProfileRequestContext;
32  
33  /**
34   * An attribute definition that generates random identifiers useful for transient subject IDs.
35   * 
36   * Information about the created IDs are stored within a provided {@link StorageService} in the form of
37   * {@link TransientIdEntry}s. Each entry is mapped under two keys; the generated ID and a key derived from the tuple
38   * (outbound message issuer, inbound message issuer, principal name).
39   */
40  public class TransientIdAttributeDefinition extends BaseAttributeDefinition {
41  
42      /** Class logger. */
43      private final Logger log = LoggerFactory.getLogger(TransientIdAttributeDefinition.class);
44  
45      /** Store used to map tokens to principals. */
46      private StorageService<String, TransientIdEntry> idStore;
47  
48      /** Storage partition in which IDs are stored. */
49      private String partition;
50  
51      /** Generator of random, hex-encoded, tokens. */
52      private IdentifierGenerator idGenerator;
53  
54      /** Size, in bytes, of the token. */
55      private int idSize;
56  
57      /** Length, in milliseconds, tokens are valid. */
58      private long idLifetime;
59  
60      /**
61       * Constructor.
62       * 
63       * @param store store used to map tokens to principals
64       * 
65       * @throws NoSuchAlgorithmException thrown if the SHA1PRNG, used as the default random number generation algorithm,
66       *             is not supported
67       */
68      public TransientIdAttributeDefinition(StorageService<String, TransientIdEntry> store)
69              throws NoSuchAlgorithmException {
70          idGenerator = new SecureRandomIdentifierGenerator();
71          idStore = store;
72          partition = "transientId";
73          idSize = 16;
74          idLifetime = 1000 * 60 * 60 * 4;
75  
76          // Prime the generator
77          idGenerator.generateIdentifier(idSize);
78      }
79  
80      /** {@inheritDoc} */
81      protected BaseAttribute doResolve(ShibbolethResolutionContext resolutionContext)
82              throws AttributeResolutionException {
83          
84          BasicAttribute<String> attribute = new BasicAttribute<String>();
85          attribute.setId(getId());
86  
87          SAMLProfileRequestContext requestContext = resolutionContext.getAttributeRequestContext();
88  
89          String principalName = requestContext.getPrincipalName();
90          if (principalName == null) {
91              log.debug("Principal name for request {} was null, no attribute returned",
92                      requestContext.getInboundSAMLMessageId());
93              return attribute;
94          }
95  
96          log.debug(
97                  "Building transient ID for request {}; outbound message issuer: {}, inbound message issuer: {}, principal identifer: {}",
98                  new Object[] { requestContext.getInboundSAMLMessageId(), requestContext.getOutboundMessageIssuer(),
99                          requestContext.getInboundMessageIssuer(), principalName, });
100         StringBuilder principalTokenIdBuilder = new StringBuilder();
101         principalTokenIdBuilder.append(requestContext.getOutboundMessageIssuer()).append("!")
102                 .append(requestContext.getInboundMessageIssuer()).append("!").append(principalName);
103         String principalTokenId = principalTokenIdBuilder.toString();
104 
105         TransientIdEntry tokenEntry = idStore.get(partition, principalTokenId);
106         if (tokenEntry == null || tokenEntry.isExpired()) {
107             String token = idGenerator.generateIdentifier(idSize);
108             tokenEntry = new TransientIdEntry(idLifetime, requestContext.getInboundMessageIssuer(), principalName,
109                     token);
110             idStore.put(partition, token, tokenEntry);
111             idStore.put(partition, principalTokenId, tokenEntry);
112         }
113 
114         log.debug("Created transient ID {} for request {}", tokenEntry.getId(),
115                 requestContext.getInboundSAMLMessageId());
116         attribute.getValues().add(tokenEntry.getId());
117 
118         return attribute;
119     }
120 
121     /**
122      * Gets the size, in bytes, of the id.
123      * 
124      * @return size, in bytes, of the id
125      */
126     public int getIdSize() {
127         return idSize;
128     }
129 
130     /**
131      * Sets the size, in bytes, of the id.
132      * 
133      * @param size size, in bytes, of the id
134      */
135     public void setIdSize(int size) {
136         idSize = size;
137     }
138 
139     /**
140      * Gets the time, in milliseconds, ids are valid.
141      * 
142      * @return time, in milliseconds, ids are valid
143      */
144     public long getIdLifetime() {
145         return idLifetime;
146     }
147 
148     /**
149      * Sets the time, in milliseconds, ids are valid.
150      * 
151      * @param lifetime time, in milliseconds, ids are valid
152      */
153     public void setTokenLiftetime(long lifetime) {
154         idLifetime = lifetime;
155     }
156 
157     /** {@inheritDoc} */
158     public void validate() throws AttributeResolutionException {
159 
160     }
161 }