/// <summary>
		/// Prepares a message for sending based on the rules of this channel binding element.
		/// </summary>
		/// <param name="message">The message to prepare for sending.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// The protections (if any) that this binding element applied to the message.
		/// Null if this binding element did not even apply to this binding element.
		/// </returns>
		/// <remarks>
		/// Implementations that provide message protection must honor the
		/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
		/// </remarks>
		public override Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
			var directResponse = message as IDirectResponseProtocolMessage;
			var request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequestInternal : null;

			// Serialize the authorization code, if there is one.
			var authCodeCarrier = message as IAuthorizationCodeCarryingRequest;
			if (authCodeCarrier != null) {
				var codeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer);
				var code = authCodeCarrier.AuthorizationDescription;
				authCodeCarrier.Code = codeFormatter.Serialize(code);
				return MessageProtectionTasks.None;
			}

			// Serialize the refresh token, if applicable.
			var refreshTokenResponse = message as AccessTokenSuccessResponse;
			if (refreshTokenResponse != null && refreshTokenResponse.HasRefreshToken) {
				var refreshTokenCarrier = (IAuthorizationCarryingRequest)message;
				var refreshToken = new RefreshToken(refreshTokenCarrier.AuthorizationDescription);
				var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore);
				refreshTokenResponse.RefreshToken = refreshTokenFormatter.Serialize(refreshToken);
			}

			// Serialize the access token, if applicable.
			var accessTokenResponse = message as IAccessTokenIssuingResponse;
			if (accessTokenResponse != null && accessTokenResponse.AuthorizationDescription != null) {
				ErrorUtilities.VerifyInternal(request != null, "We should always have a direct request message for this case.");
				accessTokenResponse.AccessToken = accessTokenResponse.AuthorizationDescription.Serialize();
			}

			return MessageProtectionTasks.Null;
		}
		/// <summary>
		/// Prepares a message for sending based on the rules of this channel binding element.
		/// </summary>
		/// <param name="message">The message to prepare for sending.</param>
		/// <returns>
		/// The protections (if any) that this binding element applied to the message.
		/// Null if this binding element did not even apply to this binding element.
		/// </returns>
		public override MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
			var directResponse = message as IDirectResponseProtocolMessage;
			IAccessTokenRequest request = directResponse != null ? directResponse.OriginatingRequest as IAccessTokenRequest : null;

			var implicitGrantResponse = message as EndUserAuthorizationSuccessAccessTokenResponse;
			if (implicitGrantResponse != null) {
				IAuthorizationCarryingRequest tokenCarryingResponse = implicitGrantResponse;
				tokenCarryingResponse.AuthorizationDescription = new AccessToken(request.ClientIdentifier, implicitGrantResponse.Scope, implicitGrantResponse.AuthorizingUsername, implicitGrantResponse.Lifetime);

				return MessageProtections.None;
			}

			var accessTokenResponse = message as AccessTokenSuccessResponse;
			if (accessTokenResponse != null) {
				var authCarryingRequest = (IAuthorizationCarryingRequest)request;
				var accessToken = new AccessToken(authCarryingRequest.AuthorizationDescription, accessTokenResponse.Lifetime);
				using (var resourceServerEncryptionKey = this.AuthorizationServer.GetResourceServerEncryptionKey(request)) {
					var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServer.AccessTokenSigningKey, resourceServerEncryptionKey);
					accessTokenResponse.AccessToken = accessTokenFormatter.Serialize(accessToken);
				}

				if (accessTokenResponse.HasRefreshToken) {
					var refreshToken = new RefreshToken(authCarryingRequest.AuthorizationDescription);
					var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore);
					accessTokenResponse.RefreshToken = refreshTokenFormatter.Serialize(refreshToken);
				}
			}

			return null;
		}
		/// <summary>
		/// Decodes a refresh token into its authorization details.
		/// </summary>
		/// <param name="refreshToken">The encoded refresh token as it would appear to the client.</param>
		/// <returns>A description of the authorization represented by the refresh token.</returns>
		/// <exception cref="ProtocolException">Thrown if the refresh token is not valid due to expiration, corruption or not being authentic.</exception>
		/// <remarks>
		/// This can be useful if the authorization server supports the client revoking its own access (on uninstall, for example).
		/// Outside the scope of the OAuth 2 spec, the client may contact the authorization server host requesting that its refresh
		/// token be revoked.  The authorization server would need to decode the refresh token so it knows which authorization in
		/// the database to delete.
		/// </remarks>
		public IAuthorizationDescription DecodeRefreshToken(string refreshToken) {
			var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServerServices.CryptoKeyStore);
			var token = new RefreshToken();
			refreshTokenFormatter.Deserialize(token, refreshToken);
			return token;
		}
		public override Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
			var authCodeCarrier = message as IAuthorizationCodeCarryingRequest;
			if (authCodeCarrier != null) {
				var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer);
				var authorizationCode = new AuthorizationCode();
				authorizationCodeFormatter.Deserialize(authorizationCode, authCodeCarrier.Code, message, Protocol.code);
				authCodeCarrier.AuthorizationDescription = authorizationCode;
			}

			var refreshTokenCarrier = message as IRefreshTokenCarryingRequest;
			if (refreshTokenCarrier != null) {
				var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore);
				var refreshToken = new RefreshToken();
				refreshTokenFormatter.Deserialize(refreshToken, refreshTokenCarrier.RefreshToken, message, Protocol.refresh_token);
				refreshTokenCarrier.AuthorizationDescription = refreshToken;
			}

			return MessageProtectionTasks.Null;
		}
		/// <summary>
		/// Prepares the response to an access token request.
		/// </summary>
		/// <param name="request">The request for an access token.</param>
		/// <param name="accessTokenEncryptingPublicKey">The crypto service provider with the public key to encrypt the access token to, such that the resource server will be able to decrypt it.</param>
		/// <param name="accessTokenLifetime">The access token's lifetime.</param>
		/// <param name="includeRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param>
		/// <returns>The response message to send to the client.</returns>
		public virtual IDirectResponseProtocolMessage PrepareAccessTokenResponse(AccessTokenRequestBase request, RSACryptoServiceProvider accessTokenEncryptingPublicKey, TimeSpan? accessTokenLifetime = null, bool includeRefreshToken = true) {
			Contract.Requires<ArgumentNullException>(request != null);
			Contract.Requires<ArgumentNullException>(accessTokenEncryptingPublicKey != null);

			var tokenRequest = (IAuthorizationCarryingRequest)request;
			using (var crypto = this.AuthorizationServerServices.CreateAccessTokenSigningCryptoServiceProvider()) {
				var accessTokenFormatter = AccessToken.CreateFormatter(crypto, accessTokenEncryptingPublicKey);
				var accessToken = new AccessToken(tokenRequest.AuthorizationDescription, accessTokenLifetime);

				var response = new AccessTokenSuccessResponse(request) {
					AccessToken = accessTokenFormatter.Serialize(accessToken),
					Lifetime = accessToken.Lifetime,
				};
				response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope);

				if (includeRefreshToken) {
					var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServerServices.CryptoKeyStore);
					var refreshToken = new RefreshToken(tokenRequest.AuthorizationDescription);
					response.RefreshToken = refreshTokenFormatter.Serialize(refreshToken);
				}

				return response;
			}
		}