//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2 { using System; using System.Collections.Generic; using System.Security.Cryptography; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth2.ChannelElements; using Validation; /// /// A short-lived token that accompanies HTTP requests to protected data to authorize the request. /// public class AccessToken : AuthorizationDataBag { /// /// Initializes a new instance of the class. /// public AccessToken() { } /// /// Gets or sets the lifetime of the access token. /// /// The lifetime. [MessagePart(Encoder = typeof(TimespanSecondsEncoder))] public TimeSpan? Lifetime { get; set; } /// /// Gets the type of this instance. /// /// The type of the bag. /// /// This ensures that one token cannot be misused as another kind of token. /// protected override Type BagType { get { // different roles (authorization server vs. Client) may derive from AccessToken, but they are all interoperable. return typeof(AccessToken); } } /// /// Creates a formatter capable of serializing/deserializing an access token. /// /// The crypto service provider with the authorization server's private key used to asymmetrically sign the access token. /// The crypto service provider with the resource server's public key used to encrypt the access token. /// An access token serializer. internal static IDataBagFormatter CreateFormatter(RSACryptoServiceProvider signingKey, RSACryptoServiceProvider encryptingKey) { return new UriStyleMessageFormatter(signingKey, encryptingKey); } /// /// Creates a formatter capable of serializing/deserializing an access token. /// /// The symmetric key store. /// /// An access token serializer. /// internal static IDataBagFormatter CreateFormatter(ICryptoKeyStore symmetricKeyStore) { Requires.NotNull(symmetricKeyStore, "symmetricKeyStore"); return new UriStyleMessageFormatter(symmetricKeyStore, bucket: "AccessTokens", signed: true, encrypted: true); } /// /// Initializes this instance of the class. /// /// The authorization to apply to this access token. internal void ApplyAuthorization(IAuthorizationDescription authorization) { Requires.NotNull(authorization, "authorization"); this.ClientIdentifier = authorization.ClientIdentifier; this.UtcCreationDate = authorization.UtcIssued; this.User = authorization.User; this.Scope.ResetContents(authorization.Scope); } /// /// Initializes this instance of the class. /// /// The scopes. /// The username of the account that authorized this token. /// The lifetime for this access token. /// /// The is left null in this case because this constructor /// is invoked in the case where the client is not authenticated, and therefore no /// trust in the client_id is appropriate. /// internal void ApplyAuthorization(IEnumerable scopes, string username, TimeSpan? lifetime) { this.Scope.ResetContents(scopes); this.User = username; this.Lifetime = lifetime; this.UtcCreationDate = DateTime.UtcNow; } /// /// Serializes this instance to a simple string for transmission to the client. /// /// A non-empty string. protected internal virtual string Serialize() { throw new NotSupportedException(); } /// /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// /// /// Some messages have required fields, or combinations of fields that must relate to each other /// in specialized ways. After deserializing a message, this method checks the state of the /// message to see if it conforms to the protocol. /// Note that this property should not check signatures or perform any state checks /// outside this scope of this particular message. /// /// Thrown if the message is invalid. protected override void EnsureValidMessage() { base.EnsureValidMessage(); // Has this token expired? if (this.Lifetime.HasValue) { DateTime expirationDate = this.UtcCreationDate + this.Lifetime.Value; if (expirationDate < DateTime.UtcNow) { throw new ExpiredMessageException(expirationDate, this.ContainingMessage); } } } } }