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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
//-----------------------------------------------------------------------
// <copyright file="RequestBase.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Messages {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
/// <summary>
/// A common base class for OpenID request messages and indirect responses (since they are ultimately requests).
/// </summary>
[DebuggerDisplay("OpenID {Version} {Mode}")]
[Serializable]
internal class RequestBase : IDirectedProtocolMessage {
/// <summary>
/// The openid.ns parameter in the message.
/// </summary>
/// <value>"http://specs.openid.net/auth/2.0" </value>
/// <remarks>
/// This particular value MUST be present for the request to be a valid OpenID Authentication 2.0 request. Future versions of the specification may define different values in order to allow message recipients to properly interpret the request.
/// </remarks>
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Read by reflection.")]
[MessagePart("openid.ns", IsRequired = true, AllowEmpty = false, MinVersion = "2.0")]
#pragma warning disable 0414 // read by reflection
private readonly string OpenIdNamespace = Protocol.OpenId2Namespace;
#pragma warning restore 0414
/// <summary>
/// Backing store for the <see cref="ExtraData"/> property.
/// </summary>
private readonly Dictionary<string, string> extraData = new Dictionary<string, string>();
/// <summary>
/// Backing store for the <see cref="Incoming"/> property.
/// </summary>
private bool incoming;
/// <summary>
/// Initializes a new instance of the <see cref="RequestBase"/> class.
/// </summary>
/// <param name="version">The OpenID version this message must comply with.</param>
/// <param name="providerEndpoint">The OpenID Provider endpoint.</param>
/// <param name="mode">The value for the openid.mode parameter.</param>
/// <param name="transport">A value indicating whether the message will be transmitted directly or indirectly.</param>
protected RequestBase(Version version, Uri providerEndpoint, string mode, MessageTransport transport) {
Requires.NotNull(providerEndpoint, "providerEndpoint");
Requires.NotNullOrEmpty(mode, "mode");
this.Recipient = providerEndpoint;
this.Mode = mode;
this.Transport = transport;
this.Version = version;
}
/// <summary>
/// Gets the value of the openid.mode parameter.
/// </summary>
[MessagePart("openid.mode", IsRequired = true, AllowEmpty = false)]
public string Mode { get; private set; }
#region IDirectedProtocolMessage Members
/// <summary>
/// Gets the preferred method of transport for the message.
/// </summary>
/// <value>
/// For direct messages this is the OpenID mandated POST.
/// For indirect messages both GET and POST are allowed.
/// </value>
HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods {
get {
// OpenID 2.0 section 5.1.1
HttpDeliveryMethods methods = HttpDeliveryMethods.PostRequest;
if (this.Transport == MessageTransport.Indirect) {
methods |= HttpDeliveryMethods.GetRequest;
}
return methods;
}
}
/// <summary>
/// Gets the recipient of the message.
/// </summary>
/// <value>The OP endpoint, or the RP return_to.</value>
public Uri Recipient {
get;
private set;
}
#endregion
#region IProtocolMessage Properties
/// <summary>
/// Gets the version of the protocol this message is prepared to implement.
/// </summary>
/// <value>Version 2.0</value>
public Version Version { get; private set; }
/// <summary>
/// Gets the level of protection this message requires.
/// </summary>
/// <value><see cref="MessageProtections.None"/></value>
public virtual MessageProtections RequiredProtection {
get { return MessageProtections.None; }
}
/// <summary>
/// Gets a value indicating whether this is a direct or indirect message.
/// </summary>
/// <value><see cref="MessageTransport.Direct"/></value>
public MessageTransport Transport { get; private set; }
/// <summary>
/// Gets the extra parameters included in the message.
/// </summary>
/// <value>An empty dictionary.</value>
public IDictionary<string, string> ExtraData {
get { return this.extraData; }
}
#endregion
/// <summary>
/// Gets a value indicating whether this message was deserialized as an incoming message.
/// </summary>
protected internal bool Incoming {
get { return this.incoming; }
}
/// <summary>
/// Gets the protocol used by this message.
/// </summary>
protected Protocol Protocol {
get { return Protocol.Lookup(this.Version); }
}
#region IProtocolMessage Methods
/// <summary>
/// Checks the message state for conformity to the protocol specification
/// and throws an exception if the message is invalid.
/// </summary>
/// <remarks>
/// <para>Some messages have required fields, or combinations of fields that must relate to each other
/// in specialized ways. After deserializing a message, this method checks the state of the
/// message to see if it conforms to the protocol.</para>
/// <para>Note that this property should <i>not</i> check signatures or perform any state checks
/// outside this scope of this particular message.</para>
/// </remarks>
/// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
public virtual void EnsureValidMessage() {
}
#endregion
/// <summary>
/// Sets a flag indicating that this message is received (as opposed to sent).
/// </summary>
internal void SetAsIncoming() {
this.incoming = true;
}
/// <summary>
/// Gets some string from a given version of the OpenID protocol.
/// </summary>
/// <param name="protocolVersion">The protocol version to use for lookup.</param>
/// <param name="mode">A function that can retrieve the desired protocol constant.</param>
/// <returns>The value of the constant.</returns>
/// <remarks>
/// This method can be used by a constructor to throw an <see cref="ArgumentNullException"/>
/// instead of a <see cref="NullReferenceException"/>.
/// </remarks>
protected static string GetProtocolConstant(Version protocolVersion, Func<Protocol, string> mode) {
Requires.NotNull(protocolVersion, "protocolVersion");
return mode(Protocol.Lookup(protocolVersion));
}
}
}
|