summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Behaviors/GsaIcamProfile.cs
blob: 62382cd332bed62e2db932bdb185ce9cfeaa096e (plain)
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
//-----------------------------------------------------------------------
// <copyright file="GsaIcamProfile.cs" company="Outercurve Foundation">
//     Copyright (c) Outercurve Foundation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DotNetOpenAuth.OpenId.RelyingParty.Behaviors {
	using System;
	using System.Diagnostics.CodeAnalysis;
	using System.Linq;
	using DotNetOpenAuth.Configuration;
	using DotNetOpenAuth.Logging;
	using DotNetOpenAuth.Messaging;
	using DotNetOpenAuth.OpenId.Behaviors;
	using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
	using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy;
	using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
	using DotNetOpenAuth.OpenId.RelyingParty;

	/// <summary>
	/// Implements the Identity, Credential, &amp; Access Management (ICAM) OpenID 2.0 Profile
	/// for the General Services Administration (GSA).
	/// </summary>
	/// <remarks>
	/// <para>Relying parties that include this profile are always held to the terms required by the profile,
	/// but Providers are only affected by the special behaviors of the profile when the RP specifically
	/// indicates that they want to use this profile. </para>
	/// </remarks>
	[Serializable]
	[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Icam", Justification = "Acronym")]
	public sealed class GsaIcamProfile : GsaIcamProfileBase, IRelyingPartyBehavior {
		/// <summary>
		/// Initializes a new instance of the <see cref="GsaIcamProfile"/> class.
		/// </summary>
		public GsaIcamProfile() {
			if (DisableSslRequirement) {
				Logger.OpenId.Warn("GSA level 1 behavior has its RequireSsl requirement disabled.");
			}
		}

		#region IRelyingPartyBehavior Members

		/// <summary>
		/// Applies a well known set of security requirements.
		/// </summary>
		/// <param name="securitySettings">The security settings to enhance with the requirements of this profile.</param>
		/// <remarks>
		/// Care should be taken to never decrease security when applying a profile.
		/// Profiles should only enhance security requirements to avoid being
		/// incompatible with each other.
		/// </remarks>
		void IRelyingPartyBehavior.ApplySecuritySettings(RelyingPartySecuritySettings securitySettings) {
			if (securitySettings.MaximumHashBitLength < 256) {
				securitySettings.MaximumHashBitLength = 256;
			}

			securitySettings.RequireSsl = !DisableSslRequirement;
			securitySettings.RequireDirectedIdentity = true;
			securitySettings.RequireAssociation = true;
			securitySettings.RejectDelegatingIdentifiers = true;
			securitySettings.IgnoreUnsignedExtensions = true;
			securitySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
		}

		/// <summary>
		/// Called when an authentication request is about to be sent.
		/// </summary>
		/// <param name="request">The request.</param>
		void IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(RelyingParty.IAuthenticationRequest request) {
			RelyingParty.AuthenticationRequest requestInternal = (RelyingParty.AuthenticationRequest)request;
			ErrorUtilities.VerifyProtocol(string.Equals(request.Realm.Scheme, Uri.UriSchemeHttps, StringComparison.Ordinal) || DisableSslRequirement, BehaviorStrings.RealmMustBeHttps);

			var pape = requestInternal.AppliedExtensions.OfType<PolicyRequest>().SingleOrDefault();
			if (pape == null) {
				request.AddExtension(pape = new PolicyRequest());
			}

			if (!pape.PreferredPolicies.Contains(AuthenticationPolicies.PrivatePersonalIdentifier)) {
				pape.PreferredPolicies.Add(AuthenticationPolicies.PrivatePersonalIdentifier);
			}

			if (!pape.PreferredPolicies.Contains(AuthenticationPolicies.USGovernmentTrustLevel1)) {
				pape.PreferredPolicies.Add(AuthenticationPolicies.USGovernmentTrustLevel1);
			}

			if (!AllowPersonallyIdentifiableInformation && !pape.PreferredPolicies.Contains(AuthenticationPolicies.NoPersonallyIdentifiableInformation)) {
				pape.PreferredPolicies.Add(AuthenticationPolicies.NoPersonallyIdentifiableInformation);
			}

			if (pape.PreferredPolicies.Contains(AuthenticationPolicies.NoPersonallyIdentifiableInformation)) {
				ErrorUtilities.VerifyProtocol(
					(!requestInternal.AppliedExtensions.OfType<ClaimsRequest>().Any() &&
					!requestInternal.AppliedExtensions.OfType<FetchRequest>().Any()),
					BehaviorStrings.PiiIncludedWithNoPiiPolicy);
			}

			Reporting.RecordEventOccurrence(this, "RP");
		}

		/// <summary>
		/// Called when an incoming positive assertion is received.
		/// </summary>
		/// <param name="assertion">The positive assertion.</param>
		void IRelyingPartyBehavior.OnIncomingPositiveAssertion(IAuthenticationResponse assertion) {
			PolicyResponse pape = assertion.GetExtension<PolicyResponse>();
			ErrorUtilities.VerifyProtocol(
				pape != null &&
				pape.ActualPolicies.Contains(AuthenticationPolicies.USGovernmentTrustLevel1) &&
				pape.ActualPolicies.Contains(AuthenticationPolicies.PrivatePersonalIdentifier),
				BehaviorStrings.PapeResponseOrRequiredPoliciesMissing);

			ErrorUtilities.VerifyProtocol(AllowPersonallyIdentifiableInformation || pape.ActualPolicies.Contains(AuthenticationPolicies.NoPersonallyIdentifiableInformation), BehaviorStrings.PapeResponseOrRequiredPoliciesMissing);

			if (pape.ActualPolicies.Contains(AuthenticationPolicies.NoPersonallyIdentifiableInformation)) {
				ErrorUtilities.VerifyProtocol(
					assertion.GetExtension<ClaimsResponse>() == null &&
					assertion.GetExtension<FetchResponse>() == null,
					BehaviorStrings.PiiIncludedWithNoPiiPolicy);
			}
		}

		#endregion
	}
}