//
// 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;
//}
}