//-----------------------------------------------------------------------
//
// Copyright (c) Andrew Arnott. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OAuth2 {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2.Messages;
using Validation;
///
/// A base class for extensions that apply client authentication to messages for the authorization server in specific ways.
///
public abstract class ClientCredentialApplicator {
///
/// Initializes a new instance of the class.
///
protected ClientCredentialApplicator() {
}
///
/// Transmits the secret the client shares with the authorization server as a parameter in the POST entity payload.
///
/// The secret the client shares with the authorization server.
/// The credential applicator to provide to the instance.
public static ClientCredentialApplicator PostParameter(string clientSecret) {
Requires.NotNullOrEmpty(clientSecret, "clientSecret");
return new PostParameterApplicator(clientSecret);
}
///
/// Transmits the client identifier and secret in the HTTP Authorization header via HTTP Basic authentication.
///
/// The client id and secret.
/// The credential applicator to provide to the instance.
public static ClientCredentialApplicator NetworkCredential(NetworkCredential credential) {
Requires.NotNull(credential, "credential");
return new NetworkCredentialApplicator(credential);
}
///
/// Transmits the client identifier and secret in the HTTP Authorization header via HTTP Basic authentication.
///
/// The secret the client shares with the authorization server.
/// The credential applicator to provide to the instance.
public static ClientCredentialApplicator NetworkCredential(string clientSecret) {
Requires.NotNullOrEmpty(clientSecret, "clientSecret");
return new NetworkCredentialApplicator(clientSecret);
}
///
/// Never transmits a secret. Useful for anonymous clients or clients unable to keep a secret.
///
/// The credential applicator to provide to the instance.
public static ClientCredentialApplicator NoSecret() {
return null;
}
///
/// Applies the client identifier and (when applicable) the client authentication to an outbound message.
///
/// The identifier by which the authorization server should recognize this client.
/// The outbound message to apply authentication information to.
public virtual void ApplyClientCredential(string clientIdentifier, AuthenticatedClientRequestBase request) {
}
///
/// Applies the client identifier and (when applicable) the client authentication to an outbound message.
///
/// The identifier by which the authorization server should recognize this client.
/// The outbound message to apply authentication information to.
public virtual void ApplyClientCredential(string clientIdentifier, HttpRequestMessage request) {
}
///
/// Authenticates the client via HTTP Basic.
///
private class NetworkCredentialApplicator : ClientCredentialApplicator {
///
/// The client identifier and secret.
///
private readonly NetworkCredential credential;
///
/// The client secret.
///
private readonly string clientSecret;
///
/// Initializes a new instance of the class.
///
/// The client secret.
internal NetworkCredentialApplicator(string clientSecret) {
Requires.NotNullOrEmpty(clientSecret, "clientSecret");
this.clientSecret = clientSecret;
}
///
/// Initializes a new instance of the class.
///
/// The client credential.
internal NetworkCredentialApplicator(NetworkCredential credential) {
Requires.NotNull(credential, "credential");
this.credential = credential;
}
///
/// Applies the client identifier and (when applicable) the client authentication to an outbound message.
///
/// The identifier by which the authorization server should recognize this client.
/// The outbound message to apply authentication information to.
public override void ApplyClientCredential(string clientIdentifier, AuthenticatedClientRequestBase request) {
// When using network credentials, the client authentication is not done as standard message parts.
request.ClientIdentifier = null;
request.ClientSecret = null;
}
///
/// Applies the client identifier and (when applicable) the client authentication to an outbound message.
///
/// The identifier by which the authorization server should recognize this client.
/// The outbound message to apply authentication information to.
public override void ApplyClientCredential(string clientIdentifier, HttpRequestMessage request) {
if (clientIdentifier != null) {
if (this.credential != null) {
ErrorUtilities.VerifyHost(
string.Equals(this.credential.UserName, clientIdentifier, StringComparison.Ordinal),
"Client identifiers \"{0}\" and \"{1}\" do not match.",
this.credential.UserName,
clientIdentifier);
}
// HttpWebRequest ignores the Credentials property until the remote server returns a 401 Unauthorized.
// So we also set the HTTP Authorization request header directly.
OAuthUtilities.ApplyHttpBasicAuth(request.Headers, clientIdentifier, this.clientSecret);
}
}
}
///
/// Authenticates the client via a client_secret parameter in the message.
///
private class PostParameterApplicator : ClientCredentialApplicator {
///
/// The client secret.
///
private readonly string secret;
///
/// Initializes a new instance of the class.
///
/// The client secret.
internal PostParameterApplicator(string clientSecret) {
Requires.NotNullOrEmpty(clientSecret, "clientSecret");
this.secret = clientSecret;
}
///
/// Applies the client identifier and (when applicable) the client authentication to an outbound message.
///
/// The identifier by which the authorization server should recognize this client.
/// The outbound message to apply authentication information to.
public override void ApplyClientCredential(string clientIdentifier, AuthenticatedClientRequestBase request) {
if (clientIdentifier != null) {
request.ClientSecret = this.secret;
}
}
}
}
}