// // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // TODO: Can I really donate this code? Get approval from Kent and MS LGA. //----------------------------------------------------------------------------- // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // // //----------------------------------------------------------------------------- using System; using System.Security.Cryptography.X509Certificates; using System.ServiceModel; using System.Web; using System.Web.Configuration; using Microsoft.IdentityModel.Claims; using Microsoft.IdentityModel.Configuration; using Microsoft.IdentityModel.Protocols.WSTrust; using Microsoft.IdentityModel.SecurityTokenService; using Trade.PassiveStsModelClasses; using System.Xml; /// /// A custom SecurityTokenService implementation. /// public class CustomSecurityTokenService : SecurityTokenService { /// /// Creates an instance of CustomSecurityTokenService. /// /// The SecurityTokenServiceConfiguration. public CustomSecurityTokenService( SecurityTokenServiceConfiguration configuration ) : base( configuration ) { } /// /// Validates appliesTo and throws an exception if the appliesTo is null or appliesTo contains some unexpected address. /// /// The AppliesTo parameter in the request that came in (RST) void ValidateAppliesTo( EndpointAddress appliesTo ) { if ( appliesTo == null ) { throw new InvalidRequestException( "The AppliesTo is null." ); } //TODO: Enable applies to validation for your allowed relying party Urls by setting enableAppliesToValidation to true. By default it is false //if ( enableAppliesToValidation ) //{ // bool validAppliesTo = false; // foreach ( string rpUrl in PassiveRedirectBasedClaimsAwareWebApps ) // { // if ( appliesTo.Uri.Equals( new Uri( rpUrl ) ) ) // { // validAppliesTo = true; // break; // } // } // if ( !validAppliesTo ) // { // throw new InvalidRequestException( String.Format( "The AppliesTo address {0} is not valid.", appliesTo.Uri.AbsoluteUri ) ); // } //} } /// /// This method returns the configuration for the token issuance request. The configuration /// is represented by the Scope class. In our case, we are only capable of issuing a token for a /// single RP identity represented by the EncryptingCertificateName. /// /// The caller's principal /// The incoming RST /// The scope information to be used for the token-issuance. protected override Scope GetScope( IClaimsPrincipal principal, RequestSecurityToken request ) { ValidateAppliesTo( request.AppliesTo ); Scope scope = new Scope( request.AppliesTo.Uri.AbsoluteUri, SecurityTokenServiceConfiguration.SigningCredentials ); string encryptingCertificateName = WebConfigurationManager.AppSettings[ "EncryptingCertificateName" ]; if (!string.IsNullOrEmpty(encryptingCertificateName)) { scope.EncryptingCredentials = new X509EncryptingCredentials( CertificateUtil.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, encryptingCertificateName)); } else { scope.TokenEncryptionRequired = false; scope.SymmetricKeyEncryptionRequired = false; } // Set the ReplyTo address for the WS-Federation passive protocol (wreply). This is the address to which responses will be directed. scope.ReplyToAddress = scope.AppliesToAddress; return scope; } /// /// This method returns the claims to be issued in the token. /// /// The scope information corresponding to this request. /// The caller's principal /// The incoming RST, we don't use this in our implementation /// The outgoing claimsIdentity to be included in the issued token. /// /// This method returns the claims to be issued in the token. /// /// The scope information corresponding to this request. /// The caller's principal /// The incoming RST, we don't use this in our implementation /// The outgoing claimsIdentity to be included in the issued token. protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope) { if (null == principal) { throw new InvalidRequestException("The caller's principal is null."); } AccountDataModel account = (AccountDataModel)HttpContext.Current.Session["UserInfo"]; ClaimsIdentity outputIdentity = new ClaimsIdentity("passive", System.IdentityModel.Claims.ClaimTypes.NameIdentifier, "http://microsoft/role"); Claim nameIdentifier = new Claim(System.IdentityModel.Claims.ClaimTypes.NameIdentifier, account.profileID.ToString() + "@stonehenge.com"); nameIdentifier.Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "http://schemas.xmlsoap.org/claims/UPN"; outputIdentity.Claims.Add(nameIdentifier); outputIdentity.Claims.Add(new Claim("http://microsoft/role", "staff")); outputIdentity.Claims.Add(new Claim(ClaimTypes.AuthenticationMethod, "http://microsoft/geneva")); outputIdentity.Claims.Add(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.Utc))); return outputIdentity; } //protected override RequestSecurityTokenResponse GetResponse(RequestSecurityToken request, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) //{ // RequestSecurityTokenResponse response = base.GetResponse(request, tokenDescriptor); // response.Lifetime = null; // response.RequestedAttachedReference = null; // response.RequestedUnattachedReference = null; // response.TokenType = null; // response.RequestType = null; // response.KeyType = null; // return response; //} }