Skip to content
This repository was archived by the owner on Mar 20, 2019. It is now read-only.

Commit 74b6b4e

Browse files
committed
Adds a WebAPI sample that is its own authorization server and resource server.
1 parent 798fa1c commit 74b6b4e

115 files changed

Lines changed: 34137 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Web;
2+
using System.Web.Optimization;
3+
4+
namespace OAuth2ProtectedWebApi {
5+
public class BundleConfig {
6+
// For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
7+
public static void RegisterBundles(BundleCollection bundles) {
8+
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
9+
"~/Scripts/jquery-{version}.js"));
10+
11+
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
12+
"~/Scripts/jquery-ui-{version}.js"));
13+
14+
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
15+
"~/Scripts/jquery.unobtrusive*",
16+
"~/Scripts/jquery.validate*"));
17+
18+
// Use the development version of Modernizr to develop with and learn from. Then, when you're
19+
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
20+
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
21+
"~/Scripts/modernizr-*"));
22+
23+
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
24+
25+
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
26+
"~/Content/themes/base/jquery.ui.core.css",
27+
"~/Content/themes/base/jquery.ui.resizable.css",
28+
"~/Content/themes/base/jquery.ui.selectable.css",
29+
"~/Content/themes/base/jquery.ui.accordion.css",
30+
"~/Content/themes/base/jquery.ui.autocomplete.css",
31+
"~/Content/themes/base/jquery.ui.button.css",
32+
"~/Content/themes/base/jquery.ui.dialog.css",
33+
"~/Content/themes/base/jquery.ui.slider.css",
34+
"~/Content/themes/base/jquery.ui.tabs.css",
35+
"~/Content/themes/base/jquery.ui.datepicker.css",
36+
"~/Content/themes/base/jquery.ui.progressbar.css",
37+
"~/Content/themes/base/jquery.ui.theme.css"));
38+
}
39+
}
40+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Web;
2+
using System.Web.Mvc;
3+
4+
namespace OAuth2ProtectedWebApi {
5+
public class FilterConfig {
6+
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
7+
filters.Add(new HandleErrorAttribute());
8+
}
9+
}
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Web;
5+
using System.Web.Mvc;
6+
using System.Web.Routing;
7+
8+
namespace OAuth2ProtectedWebApi {
9+
public class RouteConfig {
10+
public static void RegisterRoutes(RouteCollection routes) {
11+
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
12+
13+
routes.MapRoute(
14+
name: "Default",
15+
url: "{controller}/{action}/{id}",
16+
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
17+
);
18+
}
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace OAuth2ProtectedWebApi {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Web.Http;
6+
7+
using OAuth2ProtectedWebApi.Code;
8+
9+
public static class WebApiConfig {
10+
public static void Register(HttpConfiguration config) {
11+
config.Routes.MapHttpRoute(
12+
name: "DefaultApi",
13+
routeTemplate: "api/{controller}/{id}",
14+
defaults: new { id = RouteParameter.Optional }
15+
);
16+
17+
config.MessageHandlers.Add(new BearerTokenHandler());
18+
}
19+
}
20+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
namespace OAuth2ProtectedWebApi {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Web;
6+
using DotNetOpenAuth.Messaging.Bindings;
7+
using DotNetOpenAuth.OAuth2;
8+
using DotNetOpenAuth.OAuth2.ChannelElements;
9+
using DotNetOpenAuth.OAuth2.Messages;
10+
using OAuth2ProtectedWebApi.Code;
11+
12+
public class AuthorizationServerHost : IAuthorizationServerHost {
13+
private static ICryptoKeyStore cryptoKeyStore = MemoryCryptoKeyStore.Instance;
14+
15+
private static INonceStore nonceStore = new MemoryNonceStore();
16+
17+
public ICryptoKeyStore CryptoKeyStore {
18+
get { return cryptoKeyStore; }
19+
}
20+
21+
public INonceStore NonceStore {
22+
get { return nonceStore; }
23+
}
24+
25+
public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage) {
26+
var accessToken = new AuthorizationServerAccessToken();
27+
accessToken.Lifetime = TimeSpan.FromHours(1);
28+
accessToken.SymmetricKeyStore = this.CryptoKeyStore;
29+
var result = new AccessTokenResult(accessToken);
30+
return result;
31+
}
32+
33+
public IClientDescription GetClient(string clientIdentifier) {
34+
return new ClientDescription("zzz", new Uri("http://www.microsoft.com/en-us/default.aspx"), ClientType.Confidential);
35+
}
36+
37+
public bool IsAuthorizationValid(IAuthorizationDescription authorization) {
38+
return true;
39+
}
40+
41+
public AutomatedUserAuthorizationCheckResponse CheckAuthorizeResourceOwnerCredentialGrant(string userName, string password, IAccessTokenRequest accessRequest) {
42+
throw new NotSupportedException();
43+
}
44+
45+
public AutomatedAuthorizationCheckResponse CheckAuthorizeClientCredentialsGrant(IAccessTokenRequest accessRequest) {
46+
throw new NotSupportedException();
47+
}
48+
}
49+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
namespace OAuth2ProtectedWebApi.Code {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Net.Http;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using System.Web;
9+
10+
using DotNetOpenAuth.OAuth2;
11+
12+
public class BearerTokenHandler : DelegatingHandler {
13+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
14+
if (request.Headers.Authorization != null) {
15+
if (request.Headers.Authorization.Scheme == "Bearer") {
16+
string bearer = request.Headers.Authorization.Parameter;
17+
var resourceServer = new ResourceServer(new StandardAccessTokenAnalyzer(MemoryCryptoKeyStore.Instance));
18+
var principal = await resourceServer.GetPrincipalAsync(request, cancellationToken);
19+
HttpContext.Current.User = principal;
20+
Thread.CurrentPrincipal = principal;
21+
}
22+
}
23+
24+
return await base.SendAsync(request, cancellationToken);
25+
}
26+
}
27+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace OAuth2ProtectedWebApi.Code {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Web;
6+
using System.Web.Mvc;
7+
8+
/// <summary>
9+
/// Represents an attribute that is used to add HTTP Headers to a Controller Action response.
10+
/// </summary>
11+
public class HttpHeaderAttribute : ActionFilterAttribute {
12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="HttpHeaderAttribute"/> class.
14+
/// </summary>
15+
/// <param name="name">The HTTP header name.</param>
16+
/// <param name="value">The HTTP header value.</param>
17+
public HttpHeaderAttribute(string name, string value) {
18+
this.Name = name;
19+
this.Value = value;
20+
}
21+
22+
/// <summary>
23+
/// Gets or sets the name of the HTTP Header.
24+
/// </summary>
25+
public string Name { get; set; }
26+
27+
/// <summary>
28+
/// Gets or sets the value of the HTTP Header.
29+
/// </summary>
30+
public string Value { get; set; }
31+
32+
/// <summary>
33+
/// Called by the MVC framework after the action result executes.
34+
/// </summary>
35+
/// <param name="filterContext">The filter context.</param>
36+
public override void OnResultExecuted(ResultExecutedContext filterContext) {
37+
filterContext.HttpContext.Response.AppendHeader(this.Name, this.Value);
38+
base.OnResultExecuted(filterContext);
39+
}
40+
}
41+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace OAuth2ProtectedWebApi.Code {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Web;
6+
7+
using DotNetOpenAuth.Messaging.Bindings;
8+
9+
internal class MemoryCryptoKeyStore : ICryptoKeyStore {
10+
private Dictionary<string, Dictionary<string, CryptoKey>> keys = new Dictionary<string, Dictionary<string, CryptoKey>>();
11+
12+
private MemoryCryptoKeyStore() {
13+
}
14+
15+
internal static ICryptoKeyStore Instance = new MemoryCryptoKeyStore();
16+
17+
public CryptoKey GetKey(string bucket, string handle) {
18+
Dictionary<string, CryptoKey> keyBucket;
19+
if (this.keys.TryGetValue(bucket, out keyBucket)) {
20+
CryptoKey key;
21+
if (keyBucket.TryGetValue(handle, out key)) {
22+
return key;
23+
}
24+
}
25+
26+
return null;
27+
}
28+
29+
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
30+
Dictionary<string, CryptoKey> keyBucket;
31+
if (this.keys.TryGetValue(bucket, out keyBucket)) {
32+
foreach (var cryptoKey in keyBucket) {
33+
yield return cryptoKey;
34+
}
35+
}
36+
}
37+
38+
public void StoreKey(string bucket, string handle, CryptoKey key) {
39+
Dictionary<string, CryptoKey> keyBucket;
40+
if (!this.keys.TryGetValue(bucket, out keyBucket)) {
41+
keyBucket = this.keys[bucket] = new Dictionary<string, CryptoKey>();
42+
}
43+
44+
keyBucket[handle] = key;
45+
}
46+
47+
public void RemoveKey(string bucket, string handle) {
48+
Dictionary<string, CryptoKey> keyBucket;
49+
if (this.keys.TryGetValue(bucket, out keyBucket)) {
50+
keyBucket.Remove(handle);
51+
}
52+
}
53+
}
54+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace OAuth2ProtectedWebApi.Code {
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Web;
6+
7+
using DotNetOpenAuth.Messaging.Bindings;
8+
9+
internal class MemoryNonceStore : INonceStore {
10+
public bool StoreNonce(string context, string nonce, DateTime timestampUtc) {
11+
return true;
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)