//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2 { using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Web; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.Messages; /// /// The OAuth client for the user-agent flow, providing services for installed apps /// and in-browser Javascript widgets. /// public class UserAgentClient : ClientBase { /// /// Initializes a new instance of the class. /// /// The token issuer. /// The client identifier. /// The client secret. public UserAgentClient(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, string clientSecret = null) : base(authorizationServer, clientIdentifier, clientSecret) { } /// /// Initializes a new instance of the class. /// /// The authorization endpoint. /// The token endpoint. /// The client identifier. /// The client secret. public UserAgentClient(Uri authorizationEndpoint, Uri tokenEndpoint, string clientIdentifier = null, string clientSecret = null) : this(new AuthorizationServerDescription { AuthorizationEndpoint = authorizationEndpoint, TokenEndpoint = tokenEndpoint }, clientIdentifier, clientSecret) { Requires.NotNull(authorizationEndpoint, "authorizationEndpoint"); Requires.NotNull(tokenEndpoint, "tokenEndpoint"); } /// /// Generates a URL that the user's browser can be directed to in order to authorize /// this client to access protected data at some resource server. /// /// The scope of authorized access requested. /// The client state that should be returned with the authorization response. /// The URL that the authorization response should be sent to via a user-agent redirect. /// /// A fully-qualified URL suitable to initiate the authorization flow. /// public Uri RequestUserAuthorization(IEnumerable scope = null, string state = null, Uri returnTo = null) { var authorization = new AuthorizationState(scope) { Callback = returnTo, }; return this.RequestUserAuthorization(authorization, state: state); } /// /// Generates a URL that the user's browser can be directed to in order to authorize /// this client to access protected data at some resource server. /// /// The authorization state that is tracking this particular request. Optional. /// /// true to request an access token in the fragment of the response's URL; /// false to authenticate to the authorization server and acquire the access token (and possibly a refresh token) via a private channel. /// /// The client state that should be returned with the authorization response. /// /// A fully-qualified URL suitable to initiate the authorization flow. /// public Uri RequestUserAuthorization(IAuthorizationState authorization, bool implicitResponseType = false, string state = null) { Requires.NotNull(authorization, "authorization"); Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier)); var request = this.PrepareRequestUserAuthorization(authorization, implicitResponseType, state); return this.Channel.PrepareResponse(request).GetDirectUriRequest(this.Channel); } /// /// Scans the incoming request for an authorization response message. /// /// The actual URL of the incoming HTTP request. /// The authorization. /// The granted authorization, or null if the incoming HTTP request did not contain an authorization server response or authorization was rejected. public IAuthorizationState ProcessUserAuthorization(Uri actualRedirectUrl, IAuthorizationState authorizationState = null) { Requires.NotNull(actualRedirectUrl, "actualRedirectUrl"); if (authorizationState == null) { authorizationState = new AuthorizationState(); } var carrier = new HttpRequestInfo("GET", actualRedirectUrl); IDirectedProtocolMessage response = this.Channel.ReadFromRequest(carrier); if (response == null) { return null; } return this.ProcessUserAuthorization(authorizationState, response); } /// /// Scans the incoming request for an authorization response message. /// /// The authorization. /// The incoming authorization response message. /// /// The granted authorization, or null if the incoming HTTP request did not contain an authorization server response or authorization was rejected. /// internal IAuthorizationState ProcessUserAuthorization(IAuthorizationState authorizationState, IDirectedProtocolMessage response) { Requires.NotNull(authorizationState, "authorizationState"); Requires.NotNull(response, "response"); EndUserAuthorizationSuccessAccessTokenResponse accessTokenSuccess; EndUserAuthorizationSuccessAuthCodeResponse authCodeSuccess; if ((accessTokenSuccess = response as EndUserAuthorizationSuccessAccessTokenResponse) != null) { UpdateAuthorizationWithResponse(authorizationState, accessTokenSuccess); } else if ((authCodeSuccess = response as EndUserAuthorizationSuccessAuthCodeResponse) != null) { this.UpdateAuthorizationWithResponse(authorizationState, authCodeSuccess); } else if (response is EndUserAuthorizationFailedResponse) { authorizationState.Delete(); return null; } return authorizationState; } /// /// Generates a URL that the user's browser can be directed to in order to authorize /// this client to access protected data at some resource server. /// /// The authorization state that is tracking this particular request. Optional. /// /// true to request an access token in the fragment of the response's URL; /// false to authenticate to the authorization server and acquire the access token (and possibly a refresh token) via a private channel. /// /// The client state that should be returned with the authorization response. /// /// A message to send to the authorization server. /// internal EndUserAuthorizationRequest PrepareRequestUserAuthorization(IAuthorizationState authorization, bool implicitResponseType = false, string state = null) { Requires.NotNull(authorization, "authorization"); Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier)); if (authorization.Callback == null) { authorization.Callback = new Uri("http://localhost/"); } var request = implicitResponseType ? new EndUserAuthorizationImplicitRequest(this.AuthorizationServer) : new EndUserAuthorizationRequest(this.AuthorizationServer); request.ClientIdentifier = this.ClientIdentifier; request.Callback = authorization.Callback; request.ClientState = state; request.Scope.ResetContents(authorization.Scope); return request; } } }