1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
//-----------------------------------------------------------------------
// <copyright file="ResourceServer.cs" company="Outercurve Foundation">
// Copyright (c) Outercurve Foundation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OAuth2 {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net;
using System.Security.Principal;
using System.ServiceModel.Channels;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using ChannelElements;
using Messages;
using Messaging;
/// <summary>
/// Provides services for validating OAuth access tokens.
/// </summary>
public class ResourceServer {
/// <summary>
/// Initializes a new instance of the <see cref="ResourceServer"/> class.
/// </summary>
/// <param name="accessTokenAnalyzer">The access token analyzer.</param>
public ResourceServer(IAccessTokenAnalyzer accessTokenAnalyzer) {
Requires.NotNull(accessTokenAnalyzer, "accessTokenAnalyzer");
this.AccessTokenAnalyzer = accessTokenAnalyzer;
this.Channel = new OAuth2ResourceServerChannel();
}
/// <summary>
/// Gets the access token analyzer.
/// </summary>
/// <value>The access token analyzer.</value>
public IAccessTokenAnalyzer AccessTokenAnalyzer { get; private set; }
/// <summary>
/// Gets the channel.
/// </summary>
/// <value>The channel.</value>
internal OAuth2ResourceServerChannel Channel { get; private set; }
/// <summary>
/// Discovers what access the client should have considering the access token in the current request.
/// </summary>
/// <param name="userName">The name on the account the client has access to.</param>
/// <param name="scope">The set of operations the client is authorized for.</param>
/// <returns>An error to return to the client if access is not authorized; <c>null</c> if access is granted.</returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#", Justification = "Try pattern")]
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")]
public OutgoingWebResponse VerifyAccess(out string userName, out HashSet<string> scope) {
return this.VerifyAccess(this.Channel.GetRequestFromContext(), out userName, out scope);
}
/// <summary>
/// Discovers what access the client should have considering the access token in the current request.
/// </summary>
/// <param name="httpRequestInfo">The HTTP request info.</param>
/// <param name="userName">The name on the account the client has access to.</param>
/// <param name="scope">The set of operations the client is authorized for.</param>
/// <returns>
/// An error to return to the client if access is not authorized; <c>null</c> if access is granted.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")]
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Try pattern")]
public virtual OutgoingWebResponse VerifyAccess(HttpRequestInfo httpRequestInfo, out string userName, out HashSet<string> scope) {
Requires.NotNull(httpRequestInfo, "httpRequestInfo");
AccessProtectedResourceRequest request = null;
try {
if (this.Channel.TryReadFromRequest<AccessProtectedResourceRequest>(httpRequestInfo, out request)) {
if (this.AccessTokenAnalyzer.TryValidateAccessToken(request, request.AccessToken, out userName, out scope)) {
// No errors to return.
return null;
}
throw ErrorUtilities.ThrowProtocol("Bad access token");
} else {
var response = new UnauthorizedResponse(new ProtocolException("Missing access token"));
userName = null;
scope = null;
return this.Channel.PrepareResponse(response);
}
} catch (ProtocolException ex) {
var response = request != null ? new UnauthorizedResponse(request, ex) : new UnauthorizedResponse(ex);
userName = null;
scope = null;
return this.Channel.PrepareResponse(response);
}
}
/// <summary>
/// Discovers what access the client should have considering the access token in the current request.
/// </summary>
/// <param name="httpRequestInfo">The HTTP request info.</param>
/// <param name="principal">The principal that contains the user and roles that the access token is authorized for.</param>
/// <returns>
/// An error to return to the client if access is not authorized; <c>null</c> if access is granted.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")]
public virtual OutgoingWebResponse VerifyAccess(HttpRequestInfo httpRequestInfo, out IPrincipal principal) {
string username;
HashSet<string> scope;
var result = this.VerifyAccess(httpRequestInfo, out username, out scope);
principal = result == null ? new OAuth.ChannelElements.OAuthPrincipal(username, scope != null ? scope.ToArray() : new string[0]) : null;
return result;
}
/// <summary>
/// Discovers what access the client should have considering the access token in the current request.
/// </summary>
/// <param name="request">HTTP details from an incoming WCF message.</param>
/// <param name="requestUri">The URI of the WCF service endpoint.</param>
/// <param name="principal">The principal that contains the user and roles that the access token is authorized for.</param>
/// <returns>
/// An error to return to the client if access is not authorized; <c>null</c> if access is granted.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")]
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Try pattern")]
public virtual OutgoingWebResponse VerifyAccess(HttpRequestMessageProperty request, Uri requestUri, out IPrincipal principal) {
Requires.NotNull(request, "request");
Requires.NotNull(requestUri, "requestUri");
return this.VerifyAccess(new HttpRequestInfo(request, requestUri), out principal);
}
}
}
|