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
|
//-----------------------------------------------------------------------
// <copyright file="AssociateRequestProviderTools.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 System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Provider;
internal static class AssociateRequestProviderTools {
/// <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 static IProtocolMessage CreateResponse(IAssociateRequestProvider requestMessage, IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(requestMessage != null, "requestMessage");
Contract.Requires<ArgumentNullException>(associationStore != null);
Contract.Requires<ArgumentNullException>(securitySettings != null);
AssociateRequest request = (AssociateRequest)requestMessage;
IProtocolMessage response;
var protocol = requestMessage.GetProtocol();
if (securitySettings.IsAssociationInPermittedRange(protocol, request.AssociationType) &&
HmacShaAssociation.IsDHSessionCompatible(protocol, request.AssociationType, request.SessionType)) {
response = requestMessage.CreateResponseCore();
// Create and store the association if this is a successful response.
var successResponse = response as IAssociateSuccessfulResponseProvider;
if (successResponse != null) {
OpenIdProviderUtilities.CreateAssociation(request, successResponse, associationStore, securitySettings);
}
} else {
response = CreateUnsuccessfulResponse(requestMessage, securitySettings);
}
return response;
}
/// <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 static AssociateUnsuccessfulResponse CreateUnsuccessfulResponse(IAssociateRequestProvider requestMessage, ProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(requestMessage != null, "requestMessage");
Contract.Requires<ArgumentNullException>(securitySettings != null);
var unsuccessfulResponse = new AssociateUnsuccessfulResponse(requestMessage.Version, (AssociateRequest)requestMessage);
// 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 = requestMessage.Recipient.IsTransportSecure();
bool useDiffieHellman = !unencryptedAllowed;
var request = (AssociateRequest)requestMessage;
var protocol = requestMessage.GetProtocol();
string associationType, sessionType;
if (HmacShaAssociation.TryFindBestAssociation(protocol, false, securitySettings, useDiffieHellman, out associationType, out sessionType)) {
ErrorUtilities.VerifyInternal(request.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}'.",
request.AssociationType,
request.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.", request.AssociationType, request.SessionType);
}
return unsuccessfulResponse;
}
}
}
|