//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2.Messages { using System; using System.Collections.Generic; using System.Net; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.ChannelElements; /// /// A response from the Authorization Server to the Client containing a delegation code /// that the Client should use to obtain an access token. /// /// /// This message type is shared by the Web App, Rich App, and Username/Password profiles. /// internal class AccessTokenSuccessResponse : MessageBase, IHttpDirectResponse, IAccessTokenIssuingResponse { /// /// Initializes a new instance of the class. /// /// The request. internal AccessTokenSuccessResponse(AccessTokenRequestBase request) : base(request) { this.Scope = new HashSet(OAuthUtilities.ScopeStringComparer); this.TokenType = Protocol.AccessTokenTypes.Bearer; } /// /// Gets the HTTP status code that the direct response should be sent with. /// /// Always HttpStatusCode.OK HttpStatusCode IHttpDirectResponse.HttpStatusCode { get { return HttpStatusCode.OK; } } /// /// Gets the HTTP headers to add to the response. /// /// May be an empty collection, but must not be null. WebHeaderCollection IHttpDirectResponse.Headers { get { return new WebHeaderCollection { { HttpResponseHeader.CacheControl, "no-store" }, { HttpResponseHeader.Pragma, "no-cache" }, }; } } /// /// Gets or sets the access token. /// /// The access token. [MessagePart(Protocol.access_token, IsRequired = true)] public string AccessToken { get; internal set; } /// /// Gets or sets the token type. /// /// Usually "bearer". /// /// Described in OAuth 2.0 section 7.1. /// [MessagePart(Protocol.token_type, IsRequired = false)] // HACKHACK: This is actually required, but wasn't in older drafts of OAuth 2 public string TokenType { get; internal set; } /// /// Gets or sets the lifetime of the access token. /// /// The lifetime. [MessagePart(Protocol.expires_in, IsRequired = false, Encoder = typeof(TimespanSecondsEncoder))] public TimeSpan? Lifetime { get; internal set; } /// /// Gets or sets the refresh token. /// /// The refresh token. /// /// OPTIONAL. The refresh token used to obtain new access tokens using the same end-user access grant as described in Section 6 (Refreshing an Access Token). /// [MessagePart(Protocol.refresh_token, IsRequired = false)] public string RefreshToken { get; internal set; } /// /// Gets the scope of access being requested. /// /// The scope of the access request expressed as a list of space-delimited strings. The value of the scope parameter is defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope. [MessagePart(Protocol.scope, IsRequired = false, Encoder = typeof(ScopeEncoder))] public HashSet Scope { get; private set; } #region IAccessTokenIssuingResponse Members /// /// Gets or sets the lifetime of the access token. /// /// /// The lifetime. /// TimeSpan? IAccessTokenIssuingResponse.Lifetime { get { return this.Lifetime; } set { this.Lifetime = value; } } #endregion #region IAuthorizationCarryingRequest /// /// Gets the authorization that the token describes. /// IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { get { return ((IAccessTokenCarryingRequest)this).AuthorizationDescription; } } #endregion #region IAccessTokenCarryingRequest Members /// /// Gets or sets the authorization that the token describes. /// /// AccessToken IAccessTokenCarryingRequest.AuthorizationDescription { get; set; } /// /// Gets or sets the access token. /// string IAccessTokenCarryingRequest.AccessToken { get { return this.AccessToken; } set { this.AccessToken = value; } } #endregion /// /// Gets or sets a value indicating whether a refresh token is or should be included in the response. /// internal bool HasRefreshToken { get; set; } /// /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// /// Thrown if the message is invalid. protected override void EnsureValidMessage() { base.EnsureValidMessage(); // Per OAuth 2.0 section 4.4.3 (draft 23), refresh tokens should never be included // in a response to an access token request that used the client credential grant type. ErrorUtilities.VerifyProtocol(!this.HasRefreshToken || !(this.OriginatingRequest is AccessTokenClientCredentialsRequest), ClientAuthorizationStrings.RefreshTokenInappropriateForRequestType, this.OriginatingRequest.GetType().Name); } } }