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
|
//-----------------------------------------------------------------------
// <copyright file="AssociateRequestProvider.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Messages {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
using System.Diagnostics.Contracts;
using DotNetOpenAuth.OpenId.Provider;
internal abstract class AssociateRequestProvider : AssociateRequest {
/// <summary>
/// Initializes a new instance of the <see cref="AssociateRequestProvider"/> class.
/// </summary>
/// <param name="version">The OpenID version this message must comply with.</param>
/// <param name="providerEndpoint">The OpenID Provider endpoint.</param>
internal AssociateRequestProvider(Version version, Uri providerEndpoint)
: base(version, providerEndpoint) {
}
/// <summary>
/// Creates a Provider's response to an incoming association request.
/// </summary>
/// <param name="associationStore">The association store.</param>
/// <param name="securitySettings">The security settings on the Provider.</param>
/// <returns>
/// The appropriate association response that is ready to be sent back to the Relying Party.
/// </returns>
/// <remarks>
/// <para>If an association is created, it will be automatically be added to the provided
/// association store.</para>
/// <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
/// Failed association response messages will derive from <see cref="AssociateUnsuccessfulResponse"/>.</para>
/// </remarks>
internal IProtocolMessage CreateResponse(IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(associationStore != null);
Contract.Requires<ArgumentNullException>(securitySettings != null);
IProtocolMessage response;
if (securitySettings.IsAssociationInPermittedRange(Protocol, this.AssociationType) &&
HmacShaAssociation.IsDHSessionCompatible(Protocol, this.AssociationType, this.SessionType)) {
response = this.CreateResponseCore();
// Create and store the association if this is a successful response.
var successResponse = response as AssociateSuccessfulResponseProvider;
if (successResponse != null) {
successResponse.CreateAssociationAtProvider(this, associationStore, securitySettings);
}
} else {
response = this.CreateUnsuccessfulResponse(securitySettings);
}
return response;
}
/// <summary>
/// Creates a Provider's response to an incoming association request.
/// </summary>
/// <returns>
/// The appropriate association response message.
/// </returns>
/// <remarks>
/// <para>If an association can be successfully created, the
/// <see cref="AssociateSuccessfulResponse.CreateAssociation"/> method must not be
/// called by this method.</para>
/// <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
/// Failed association response messages will derive from <see cref="AssociateUnsuccessfulResponse"/>.</para>
/// </remarks>
protected abstract IProtocolMessage CreateResponseCore();
/// <summary>
/// Creates a response that notifies the Relying Party that the requested
/// association type is not supported by this Provider, and offers
/// an alternative association type, if possible.
/// </summary>
/// <param name="securitySettings">The security settings that apply to this Provider.</param>
/// <returns>The response to send to the Relying Party.</returns>
private AssociateUnsuccessfulResponse CreateUnsuccessfulResponse(ProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(securitySettings != null);
var unsuccessfulResponse = new AssociateUnsuccessfulResponse(this.Version, this);
// The strategy here is to suggest that the RP try again with the lowest
// permissible security settings, giving the RP the best chance of being
// able to match with a compatible request.
bool unencryptedAllowed = this.Recipient.IsTransportSecure();
bool useDiffieHellman = !unencryptedAllowed;
string associationType, sessionType;
if (HmacShaAssociation.TryFindBestAssociation(Protocol, false, securitySettings, useDiffieHellman, out associationType, out sessionType)) {
ErrorUtilities.VerifyInternal(this.AssociationType != associationType, "The RP asked for an association that should have been allowed, but the OP is trying to suggest the same one as an alternative!");
unsuccessfulResponse.AssociationType = associationType;
unsuccessfulResponse.SessionType = sessionType;
Logger.OpenId.InfoFormat(
"Association requested of type '{0}' and session '{1}', which the Provider does not support. Sending back suggested alternative of '{0}' with session '{1}'.",
this.AssociationType,
this.SessionType,
unsuccessfulResponse.AssociationType,
unsuccessfulResponse.SessionType);
} else {
Logger.OpenId.InfoFormat("Association requested of type '{0}' and session '{1}', which the Provider does not support. No alternative association type qualified for suggesting back to the Relying Party.", this.AssociationType, this.SessionType);
}
return unsuccessfulResponse;
}
}
}
|