//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2.ChannelElements { using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web; using DotNetOpenAuth.Logging; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.AuthServer.Messages; using DotNetOpenAuth.OAuth2.Messages; using Validation; /// /// The channel for the OAuth protocol. /// internal class OAuth2AuthorizationServerChannel : OAuth2ChannelBase, IOAuth2ChannelWithAuthorizationServer { /// /// The messages receivable by this channel. /// private static readonly Type[] MessageTypes = new Type[] { typeof(AccessTokenRefreshRequestAS), typeof(AccessTokenAuthorizationCodeRequestAS), typeof(AccessTokenResourceOwnerPasswordCredentialsRequest), typeof(AccessTokenClientCredentialsRequest), typeof(EndUserAuthorizationRequest), typeof(EndUserAuthorizationImplicitRequest), typeof(EndUserAuthorizationFailedResponse), }; /// /// Initializes a new instance of the class. /// /// The authorization server. /// The aggregating client authentication module. protected internal OAuth2AuthorizationServerChannel(IAuthorizationServerHost authorizationServer, ClientAuthenticationModule clientAuthenticationModule) : base(MessageTypes, InitializeBindingElements(authorizationServer, clientAuthenticationModule)) { Requires.NotNull(authorizationServer, "authorizationServer"); this.AuthorizationServer = authorizationServer; } /// /// Gets the authorization server. /// /// The authorization server. public IAuthorizationServerHost AuthorizationServer { get; private set; } /// /// Gets or sets the service that checks whether a granted set of scopes satisfies a required set of scopes. /// public IScopeSatisfiedCheck ScopeSatisfiedCheck { get; set; } /// /// Gets the protocol message that may be in the given HTTP response. /// /// The response that is anticipated to contain an protocol message. /// The cancellation token. /// /// The deserialized message parts, if found. Null otherwise. /// /// Always thrown. /// Thrown when the response is not valid. protected override Task> ReadFromResponseCoreAsync(HttpResponseMessage response, CancellationToken cancellationToken) { throw new NotImplementedException(); } /// /// Queues a message for sending in the response stream. /// /// The message to send as a response. /// /// The pending user agent redirect based message to be sent as an HttpResponse. /// /// /// This method implements spec OAuth V1.0 section 5.3. /// protected override HttpResponseMessage PrepareDirectResponse(IProtocolMessage response) { var webResponse = new HttpResponseMessage(); ApplyMessageTemplate(response, webResponse); string json = this.SerializeAsJson(response); webResponse.Content = new StringContent(json, Encoding.UTF8, JsonEncoded); return webResponse; } /// /// Gets the protocol message that may be embedded in the given HTTP request. /// /// The request to search for an embedded message. /// The cancellation token. /// /// The deserialized message, if one is found. Null otherwise. /// protected override async Task ReadFromRequestCoreAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Requires.NotNull(request, "request"); if (!string.IsNullOrEmpty(request.RequestUri.Fragment)) { var fields = HttpUtility.ParseQueryString(request.RequestUri.Fragment.Substring(1)).ToDictionary(); MessageReceivingEndpoint recipient; try { recipient = request.GetRecipient(); } catch (ArgumentException ex) { Logger.Messaging.WarnFormat("Unrecognized HTTP request: " + ex.ToString()); return null; } return (IDirectedProtocolMessage)this.Receive(fields, recipient); } return await base.ReadFromRequestCoreAsync(request, cancellationToken); } /// /// Initializes the binding elements for the OAuth channel. /// /// The authorization server. /// The aggregating client authentication module. /// /// An array of binding elements used to initialize the channel. /// private static IChannelBindingElement[] InitializeBindingElements(IAuthorizationServerHost authorizationServer, ClientAuthenticationModule clientAuthenticationModule) { Requires.NotNull(authorizationServer, "authorizationServer"); Requires.NotNull(clientAuthenticationModule, "clientAuthenticationModule"); var bindingElements = new List(); // The order they are provided is used for outgoing messgaes, and reversed for incoming messages. bindingElements.Add(new MessageValidationBindingElement(clientAuthenticationModule)); bindingElements.Add(new TokenCodeSerializationBindingElement()); return bindingElements.ToArray(); } } }