//-----------------------------------------------------------------------
//
// 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);
}
}
}
}