summaryrefslogtreecommitdiffstats
path: root/samples/OAuthServiceProvider/Code
diff options
context:
space:
mode:
Diffstat (limited to 'samples/OAuthServiceProvider/Code')
-rw-r--r--samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs3
-rw-r--r--samples/OAuthServiceProvider/Code/Global.cs10
-rw-r--r--samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs59
-rw-r--r--samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs66
-rw-r--r--samples/OAuthServiceProvider/Code/OAuthConsumer.cs14
5 files changed, 134 insertions, 18 deletions
diff --git a/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs b/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs
index 1f8f56e..f0c10d1 100644
--- a/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs
+++ b/samples/OAuthServiceProvider/Code/DatabaseNonceStore.cs
@@ -4,6 +4,7 @@
using System.Linq;
using System.Web;
using DotNetOpenAuth.Messaging.Bindings;
+ using System.Data.SqlClient;
/// <summary>
/// A database-persisted nonce store.
@@ -47,6 +48,8 @@
return true;
} catch (System.Data.Linq.DuplicateKeyException) {
return false;
+ } catch (SqlException) {
+ return false;
}
}
diff --git a/samples/OAuthServiceProvider/Code/Global.cs b/samples/OAuthServiceProvider/Code/Global.cs
index ceaeac8..7c2e9f7 100644
--- a/samples/OAuthServiceProvider/Code/Global.cs
+++ b/samples/OAuthServiceProvider/Code/Global.cs
@@ -5,6 +5,8 @@
using System.Text;
using System.Web;
using DotNetOpenAuth.OAuth.Messages;
+ using DotNetOpenAuth.OAuth2;
+ using DotNetOpenAuth.OAuth2.Messages;
/// <summary>
/// The web application global events and properties.
@@ -20,6 +22,8 @@
/// </summary>
public static log4net.ILog Logger = log4net.LogManager.GetLogger("DotNetOpenAuth.OAuthServiceProvider");
+ public static AuthorizationServer AuthorizationServer = new AuthorizationServer(new OAuth2AuthorizationServer());
+
/// <summary>
/// Gets the transaction-protected database connection for the current request.
/// </summary>
@@ -50,6 +54,12 @@
set { HttpContext.Current.Session["authrequest"] = value; }
}
+ public static EndUserAuthorizationRequest PendingOAuth2Authorization
+ {
+ get { return HttpContext.Current.Session["authrequest"] as EndUserAuthorizationRequest; }
+ set { HttpContext.Current.Session["authrequest"] = value; }
+ }
+
private static DataClassesDataContext dataContextSimple {
get {
if (HttpContext.Current != null) {
diff --git a/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs b/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs
new file mode 100644
index 0000000..00503c4
--- /dev/null
+++ b/samples/OAuthServiceProvider/Code/OAuth2AuthorizationServer.cs
@@ -0,0 +1,59 @@
+namespace OAuthServiceProvider.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Security.Cryptography;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+ using DotNetOpenAuth.OAuth2;
+ using DotNetOpenAuth.OAuth2.ChannelElements;
+
+ internal class OAuth2AuthorizationServer : IAuthorizationServer {
+ internal static readonly RSAParameters AsymmetricKey;
+
+ private static readonly byte[] secret;
+
+ private readonly INonceStore nonceStore = new DatabaseNonceStore();
+
+ static OAuth2AuthorizationServer() {
+ // For this sample, we just generate random secrets.
+ RandomNumberGenerator crypto = new RNGCryptoServiceProvider();
+ secret = new byte[16];
+ crypto.GetBytes(secret);
+
+ AsymmetricKey = new RSACryptoServiceProvider().ExportParameters(true);
+ }
+
+ #region Implementation of IAuthorizationServer
+
+ public byte[] Secret {
+ get { return secret; }
+ }
+
+ public DotNetOpenAuth.Messaging.Bindings.INonceStore VerificationCodeNonceStore {
+ get { return this.nonceStore; }
+ }
+
+ public RSAParameters AccessTokenSigningPrivateKey {
+ get { return AsymmetricKey; }
+ }
+
+ public IConsumerDescription GetClient(string clientIdentifier) {
+ var consumerRow = Global.DataContext.OAuthConsumers.SingleOrDefault(
+ consumerCandidate => consumerCandidate.ConsumerKey == clientIdentifier);
+ if (consumerRow == null) {
+ throw new ArgumentOutOfRangeException("clientIdentifier");
+ }
+
+ return consumerRow;
+ }
+
+ #endregion
+
+ public bool IsAuthorizationValid(IAuthorizationDescription authorization) {
+ // We don't support revoking tokens yet.
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs b/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs
index 6d5bfff..3c8a3be 100644
--- a/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs
+++ b/samples/OAuthServiceProvider/Code/OAuthAuthorizationManager.cs
@@ -7,8 +7,13 @@
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
- using DotNetOpenAuth;
+
+ using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth2;
+
+ using ProtocolException = System.ServiceModel.ProtocolException;
/// <summary>
/// A WCF extension to authenticate incoming messages using OAuth.
@@ -22,19 +27,16 @@
return false;
}
- HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
- Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri;
- ServiceProvider sp = Constants.CreateServiceProvider();
- try {
- var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri);
- if (auth != null) {
- var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken);
+ var httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
+ var requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri;
- var principal = sp.CreatePrincipal(auth);
+ try {
+ var principal = this.VerifyOAuth2(httpDetails, requestUri);
+ if (principal != null) {
var policy = new OAuthPrincipalAuthorizationPolicy(principal);
var policies = new List<IAuthorizationPolicy> {
- policy,
- };
+ policy,
+ };
var securityContext = new ServiceSecurityContext(policies.AsReadOnly());
if (operationContext.IncomingMessageProperties.Security != null) {
@@ -46,14 +48,13 @@
}
securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> {
- principal.Identity,
- };
+ principal.Identity,
+ };
// Only allow this method call if the access token scope permits it.
- string[] scopes = accessToken.Scope.Split('|');
- if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) {
- return true;
- }
+ return principal.IsInRole(operationContext.IncomingMessageHeaders.Action);
+ } else {
+ return false;
}
} catch (ProtocolException ex) {
Global.Logger.Error("Error processing OAuth messages.", ex);
@@ -61,5 +62,36 @@
return false;
}
+
+ private OAuthPrincipal VerifyOAuth1(HttpRequestMessageProperty httpDetails, Uri requestUri) {
+ ServiceProvider sp = Constants.CreateServiceProvider();
+ var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri);
+ if (auth != null) {
+ var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken);
+ var principal = sp.CreatePrincipal(auth);
+ return principal;
+ }
+
+ return null;
+ }
+
+ private OAuthPrincipal VerifyOAuth2(HttpRequestMessageProperty httpDetails, Uri requestUri) {
+ // for this sample where the auth server and resource server are the same site,
+ // we use the same public/private key.
+ var resourceServer = new ResourceServer(
+ new StandardAccessTokenAnalyzer(
+ OAuth2AuthorizationServer.AsymmetricKey,
+ OAuth2AuthorizationServer.AsymmetricKey));
+
+ string username;
+ HashSet<string> scope;
+ var error = resourceServer.VerifyAccess(new HttpRequestInfo(httpDetails, requestUri), out username, out scope);
+ if (error == null) {
+ var principal = new OAuthPrincipal(username, scope.ToArray());
+ return principal;
+ } else {
+ return null;
+ }
+ }
}
} \ No newline at end of file
diff --git a/samples/OAuthServiceProvider/Code/OAuthConsumer.cs b/samples/OAuthServiceProvider/Code/OAuthConsumer.cs
index d7dfc06..8291929 100644
--- a/samples/OAuthServiceProvider/Code/OAuthConsumer.cs
+++ b/samples/OAuthServiceProvider/Code/OAuthConsumer.cs
@@ -11,7 +11,7 @@ namespace OAuthServiceProvider.Code {
using System.Web;
using DotNetOpenAuth.OAuth.ChannelElements;
- public partial class OAuthConsumer : IConsumerDescription {
+ public partial class OAuthConsumer : IConsumerDescription, DotNetOpenAuth.OAuth2.IConsumerDescription {
#region IConsumerDescription Members
string IConsumerDescription.Key {
@@ -39,5 +39,17 @@ namespace OAuthServiceProvider.Code {
}
#endregion
+
+ #region IConsumerDescription Members
+
+ string DotNetOpenAuth.OAuth2.IConsumerDescription.Secret {
+ get { return this.ConsumerSecret; }
+ }
+
+ Uri DotNetOpenAuth.OAuth2.IConsumerDescription.Callback {
+ get { return string.IsNullOrEmpty(this.Callback) ? null : new Uri(this.Callback); }
+ }
+
+ #endregion
}
} \ No newline at end of file