View Javadoc

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