//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2 { using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; using System.Net; using System.Text; using DotNetOpenAuth.Messaging; /// /// Some common utility methods for OAuth 2.0. /// public static class OAuthUtilities { /// /// The instance to use when comparing scope equivalence. /// public static readonly StringComparer ScopeStringComparer = StringComparer.Ordinal; /// /// The delimiter between scope elements. /// private static char[] scopeDelimiter = new char[] { ' ' }; /// /// The characters that may appear in an access token that is included in an HTTP Authorization header. /// /// /// This is defined in OAuth 2.0 DRAFT 10, section 5.1.1. (http://tools.ietf.org/id/draft-ietf-oauth-v2-10.html#authz-header) /// private static string accessTokenAuthorizationHeaderAllowedCharacters = MessagingUtilities.UppercaseLetters + MessagingUtilities.LowercaseLetters + MessagingUtilities.Digits + @"!#$%&'()*+-./:<=>?@[]^_`{|}~\,;"; /// /// Determines whether one given scope is a subset of another scope. /// /// The requested scope, which may be a subset of . /// The granted scope, the suspected superset. /// /// true if all the elements that appear in also appear in ; /// false otherwise. /// public static bool IsScopeSubset(string requestedScope, string grantedScope) { if (string.IsNullOrEmpty(requestedScope)) { return true; } if (string.IsNullOrEmpty(grantedScope)) { return false; } var requestedScopes = new HashSet(requestedScope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries)); var grantedScopes = new HashSet(grantedScope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries)); return requestedScopes.IsSubsetOf(grantedScopes); } /// /// Identifies individual scope elements /// /// The space-delimited list of scopes. /// A set of individual scopes, with any duplicates removed. public static HashSet SplitScopes(string scope) { if (string.IsNullOrEmpty(scope)) { return new HashSet(); } return new HashSet(scope.Split(scopeDelimiter, StringSplitOptions.RemoveEmptyEntries), ScopeStringComparer); } /// /// Serializes a set of scopes as a space-delimited list. /// /// The scopes to serialize. /// A space-delimited list. public static string JoinScopes(HashSet scopes) { Requires.NotNull(scopes, "scopes"); return string.Join(" ", scopes.ToArray()); } /// /// Authorizes an HTTP request using an OAuth 2.0 access token in an HTTP Authorization header. /// /// The request to authorize. /// The access token previously obtained from the Authorization Server. internal static void AuthorizeWithBearerToken(this HttpWebRequest request, string accessToken) { Requires.NotNull(request, "request"); Requires.NotNullOrEmpty(accessToken, "accessToken"); ErrorUtilities.VerifyProtocol(accessToken.All(ch => accessTokenAuthorizationHeaderAllowedCharacters.IndexOf(ch) >= 0), OAuthStrings.AccessTokenInvalidForHttpAuthorizationHeader); request.Headers[HttpRequestHeader.Authorization] = string.Format( CultureInfo.InvariantCulture, Protocol.BearerHttpAuthorizationHeaderFormat, accessToken); } /// /// Gets information about the client with a given identifier. /// /// The authorization server. /// The client identifier. /// The client information. Never null. internal static IClientDescription GetClientOrThrow(this IAuthorizationServer authorizationServer, string clientIdentifier) { Requires.NotNullOrEmpty(clientIdentifier, "clientIdentifier"); Contract.Ensures(Contract.Result() != null); try { return authorizationServer.GetClient(clientIdentifier); } catch (KeyNotFoundException ex) { throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); } catch (ArgumentException ex) { throw ErrorUtilities.Wrap(ex, OAuthStrings.ClientOrTokenSecretNotFound); } } } }