PageRenderTime 56ms CodeModel.GetById 2ms app.highlight 47ms RepoModel.GetById 2ms app.codeStats 0ms

/src/Libraries/Thinktecture.IdentityServer.Protocols/WSFederation/HrdController.cs

https://github.com/ELEMENTSECM/Thinktecture.IdentityServer.v2
C# | 613 lines | 495 code | 101 blank | 17 comment | 58 complexity | 0f4193bfa5070530c904f45825a27512 MD5 | raw file
  1/*
  2 * Copyright (c) Dominick Baier, Brock Allen.  All rights reserved.
  3 * see license.txt
  4 */
  5
  6using System.IO;
  7using System.IdentityModel.Services.Configuration;
  8using System.Text;
  9using System.Xml;
 10using System.Xml.Linq;
 11using BrockAllen.OAuth2;
 12using Microsoft.IdentityModel.Claims;
 13using Microsoft.IdentityModel.Protocols.Saml2;
 14using Microsoft.IdentityModel.Protocols.Saml2.Constants;
 15using Microsoft.IdentityModel.Protocols.WSFederation.Metadata;
 16using Microsoft.IdentityModel.SecurityTokenService;
 17using Newtonsoft.Json.Linq;
 18using System;
 19using System.Collections.Generic;
 20using System.ComponentModel.Composition;
 21using System.IdentityModel.Selectors;
 22using System.IdentityModel.Services;
 23using System.IdentityModel.Tokens;
 24using System.Linq;
 25using System.Threading.Tasks;
 26using System.Web;
 27using System.Web.Mvc;
 28using Thinktecture.IdentityServer.Models;
 29using Thinktecture.IdentityServer.Repositories;
 30using Thinktecture.IdentityServer.TokenService;
 31using Lifetime = Microsoft.IdentityModel.Protocols.WSTrust.Lifetime;
 32using RequestSecurityTokenResponse = Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityTokenResponse;
 33using RequestedSecurityToken = Microsoft.IdentityModel.Protocols.WSTrust.RequestedSecurityToken;
 34using Claim = System.Security.Claims.Claim;
 35using ClaimTypes = System.Security.Claims.ClaimTypes;
 36using ClaimValueTypes = System.Security.Claims.ClaimValueTypes;
 37using ClaimsIdentity = System.Security.Claims.ClaimsIdentity;
 38using ClaimsPrincipal = System.Security.Claims.ClaimsPrincipal;
 39using FederatedAuthentication = Microsoft.IdentityModel.Web.FederatedAuthentication;
 40
 41namespace Thinktecture.IdentityServer.Protocols.WSFederation
 42{
 43    public class HrdController : Controller
 44    {
 45        const string _cookieName = "hrdsignout";
 46        const string _cookieNameRememberHrd = "hrdSelection";
 47        const string _cookieContext = "idsrvcontext";
 48
 49        [Import]
 50        public IConfigurationRepository ConfigurationRepository { get; set; }
 51
 52        [Import]
 53        public IIdentityProviderRepository IdentityProviderRepository { get; set; }
 54
 55
 56        public HrdController()
 57        {
 58            Container.Current.SatisfyImportsOnce(this);
 59        }
 60
 61        public HrdController(IConfigurationRepository configurationRepository, IIdentityProviderRepository identityProviderRepository)
 62        {
 63            IdentityProviderRepository = identityProviderRepository;
 64            ConfigurationRepository = configurationRepository;
 65        }
 66
 67        public ActionResult Issue()
 68        {
 69            Tracing.Verbose("HRD endpoint called.");
 70
 71            var message = WSFederationMessage.CreateFromUri(HttpContext.Request.Url);
 72
 73            // sign in 
 74            var signinMessage = message as SignInRequestMessage;
 75            if (signinMessage != null)
 76            {
 77                return ProcessSignInRequest(signinMessage);
 78            }
 79
 80            // sign out
 81            var signoutMessage = message as SignOutRequestMessage;
 82            if (signoutMessage != null)
 83            {
 84                return ProcessSignOut(signoutMessage);
 85            }
 86
 87            return View("Error");
 88        }
 89
 90        [HttpPost]
 91        [ActionName("Issue")]
 92        public ActionResult IssueResponse()
 93        {
 94            if (Request.Form.HasKeys())
 95            {
 96                if (Request.Form["SAMLResponse"] != null)
 97                {
 98                    var samlResponse = Request.Form["SAMLResponse"];
 99                    var responseDecoded = Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.HtmlDecode(samlResponse)));
100
101                    Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token;
102
103                    using (var sr = new StringReader(responseDecoded))
104                    {
105                        using (var reader = XmlReader.Create(sr))
106                        {
107                            reader.ReadToFollowing("Assertion", "urn:oasis:names:tc:SAML:2.0:assertion");
108
109                            var coll = Microsoft.IdentityModel.Tokens.SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
110
111                            token = (Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken)coll.ReadToken(reader.ReadSubtree());
112
113                        }
114                    }
115
116                    var realm = token.Assertion.Conditions.AudienceRestrictions[0].Audiences[0].ToString();
117                    var issuer = token.Assertion.Issuer.Value;
118
119                    var rstr = new RequestSecurityTokenResponse
120                                   {
121                                       TokenType = Constants.TokenKeys.TokenType,
122                                       RequestType = Constants.TokenKeys.RequestType,
123                                       KeyType = Constants.TokenKeys.KeyType,
124                                       Lifetime = new Lifetime(token.Assertion.IssueInstant, token.Assertion.Conditions.NotOnOrAfter),
125                                       AppliesTo = new System.ServiceModel.EndpointAddress(new Uri(realm)),
126                                       RequestedSecurityToken = new RequestedSecurityToken(GetElement(responseDecoded))
127                                   };
128
129                    var principal = GetClaimsIdentity(rstr);
130                    if (principal != null)
131                    {
132                        var claimsPrinciple = Microsoft.IdentityModel.Claims.ClaimsPrincipal.CreateFromPrincipal(principal);
133
134                        var requestMessage = new Microsoft.IdentityModel.Protocols.WSFederation.SignInRequestMessage(new Uri("http://foo"), realm);
135                        var ipc = new SamlTokenServiceConfiguration(issuer);
136                        SecurityTokenService identityProvider = new SamlTokenService(ipc);
137
138
139
140                        var responseMessage = Microsoft.IdentityModel.Web.FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(requestMessage, claimsPrinciple, identityProvider);
141
142                        new SignInSessionsManager(HttpContext, _cookieName, ConfigurationRepository.Global.MaximumTokenLifetime).AddEndpoint(responseMessage.BaseUri.AbsoluteUri);
143                        Microsoft.IdentityModel.Web.FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(responseMessage, System.Web.HttpContext.Current.Response);
144                    }
145                    //return new EmptyResult();
146
147                }
148                var fam = new WSFederationAuthenticationModule { FederationConfiguration = new FederationConfiguration() };
149
150                if (fam.CanReadSignInResponse(Request))
151                {
152                    var responseMessage = fam.GetSignInResponseMessage(Request);
153                    return ProcessSignInResponse(responseMessage, fam.GetSecurityToken(Request));
154                }
155            }
156
157
158            return View("Error");
159        }
160
161        #region SAML2 Helper
162        private static XmlElement GetElement(string xml)
163        {
164            var doc = new XmlDocument();
165            doc.LoadXml(xml);
166            return doc.DocumentElement;
167        }
168        public static XElement ToXElement(XmlElement xml)
169        {
170            var doc = new XmlDocument();
171
172            doc.AppendChild(doc.ImportNode(xml, true));
173
174            return XElement.Parse(doc.InnerXml);
175
176        }
177    
178        private static IClaimsPrincipal GetClaimsIdentity(RequestSecurityTokenResponse rstr)
179        {
180            var rstrXml = rstr.RequestedSecurityToken.SecurityTokenXml;
181
182            var xnm = new XmlNamespaceManager(rstrXml.OwnerDocument.NameTable);
183
184            xnm.AddNamespace(Microsoft.IdentityModel.Tokens.Saml2.Saml2Constants.Prefix, Microsoft.IdentityModel.Tokens.Saml2.Saml2Constants.Namespace);
185
186            XNamespace ast = "urn:oasis:names:tc:SAML:2.0:assertion";
187            var xElement = ToXElement(rstrXml);
188
189            var xAssertionElement = xElement.Element(ast + "Assertion");
190            if (xAssertionElement != null)
191            {
192                var xAttributeStatement = xAssertionElement.Element(ast + "AttributeStatement");
193                if (xAttributeStatement != null)
194                {
195                    var xAttributes = xAttributeStatement.Elements(ast + "Attribute");
196                    IClaimsIdentity claimsIdentity = new Microsoft.IdentityModel.Claims.ClaimsIdentity();
197                    foreach (var element in xAttributes)
198                    {
199                        var claimType = element.Attribute("NameFormat") + "/" + element.Attribute("Name");
200                        var value = element.Value;
201
202                        var xAttribute = element.Attribute("Name");
203                        if (xAttribute != null && xAttribute.Value == "urn:FirstName")
204                            claimsIdentity.Claims.Add(new Microsoft.IdentityModel.Claims.Claim(ClaimTypes.Name, element.Value));
205                        claimsIdentity.Claims.Add(new Microsoft.IdentityModel.Claims.Claim(claimType, value ?? ""));
206                    }
207                    var claimsIdentitycol = new ClaimsIdentityCollection(new[] { claimsIdentity });
208                    return Microsoft.IdentityModel.Claims.ClaimsPrincipal.CreateFromIdentities(claimsIdentitycol);
209                }
210            }
211            return null;
212        }
213        #endregion
214
215        #region Helper
216
217        private ActionResult ProcessSignInRequest(SignInRequestMessage message)
218        {
219            if (!string.IsNullOrWhiteSpace(message.HomeRealm))
220            {
221                return RedirectToIdentityProvider(message);
222            }
223            else
224            {
225                var pastHRDSelection = GetRememberHRDCookieValue();
226                if (String.IsNullOrWhiteSpace(pastHRDSelection))
227                {
228                    return ShowHomeRealmSelection(message);
229                }
230                else
231                {
232                    return ProcessHomeRealmFromCookieValue(message, pastHRDSelection);
233                }
234            }
235        }
236
237        private ActionResult ProcessHomeRealmFromCookieValue(SignInRequestMessage message, string pastHRDSelection)
238        {
239            message.HomeRealm = pastHRDSelection;
240            return ProcessSignInRequest(message);
241        }
242
243        private ActionResult ProcessSignOut(SignOutRequestMessage message)
244        {
245            // check for return url
246            if (!string.IsNullOrWhiteSpace(message.Reply))
247            {
248                ViewBag.ReturnUrl = message.Reply;
249            }
250
251            // check for existing sign in sessions
252            var mgr = new SignInSessionsManager(HttpContext, _cookieName);
253            var realms = mgr.GetEndpoints();
254            mgr.ClearEndpoints();
255            //System.IdentityModel.Services.FederatedAuthentication.SessionAuthenticationModule.SignOut();
256            //System.IdentityModel.Services.FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
257            //System.IdentityModel.Services.FederatedAuthentication.WSFederationAuthenticationModule.SignOut();
258            return View("Signout", realms);
259        }
260
261        private ActionResult ProcessSignInResponse(SignInResponseMessage responseMessage, SecurityToken token)
262        {
263            var principal = ValidateToken(token);
264            var issuerName = principal.Claims.First().Issuer;
265
266            principal.Identities.First().AddClaim(new Claim(Constants.Claims.IdentityProvider, issuerName, ClaimValueTypes.String, Constants.InternalIssuer));
267
268            var context = GetContextCookie();
269            var message = new SignInRequestMessage(new Uri("http://foo"), context.Realm);
270            message.Context = context.Wctx;
271
272            // issue token and create ws-fed response
273            var wsFedResponse = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(
274                message,
275                principal,
276                TokenServiceConfiguration.Current.CreateSecurityTokenService());
277
278            // set cookie for single-sign-out
279            new SignInSessionsManager(HttpContext, _cookieName, ConfigurationRepository.Global.MaximumTokenLifetime)
280                .SetEndpoint(context.WsFedEndpoint);
281
282            return new WSFederationResult(wsFedResponse, requireSsl: ConfigurationRepository.WSFederation.RequireSslForReplyTo);
283        }
284
285        IEnumerable<IdentityProvider> GetEnabledWSIdentityProviders()
286        {
287            return IdentityProviderRepository.GetAll().Where(
288                x => x.Enabled && x.Type == IdentityProviderTypes.WSStar);
289        }
290        IEnumerable<IdentityProvider> GetVisibleIdentityProviders()
291        {
292            return IdentityProviderRepository.GetAll().Where(
293                x => x.Enabled && x.ShowInHrdSelection);
294        }
295
296        private ClaimsPrincipal ValidateToken(SecurityToken token)
297        {
298            var config = new SecurityTokenHandlerConfiguration();
299            config.AudienceRestriction.AudienceMode = AudienceUriMode.Always;
300            config.AudienceRestriction.AllowedAudienceUris.Add(new Uri(ConfigurationRepository.Global.IssuerUri));
301
302            var registry = new IdentityProviderIssuerNameRegistry(GetEnabledWSIdentityProviders());
303            config.IssuerNameRegistry = registry;
304            config.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
305            config.CertificateValidator = X509CertificateValidator.None;
306
307            var handler = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(config);
308            var identity = handler.ValidateToken(token).First();
309
310            return new ClaimsPrincipal(identity);
311        }
312
313
314        private ActionResult ShowHomeRealmSelection(SignInRequestMessage message)
315        {
316            var idps = GetVisibleIdentityProviders();
317            if (idps.Count() == 1)
318            {
319                var ip = idps.First();
320                message.HomeRealm = ip.Name;
321                Tracing.Verbose("Only one HRD option available: " + message.HomeRealm);
322                return RedirectToIdentityProvider(ip, message);
323            }
324            else
325            {
326                Tracing.Verbose("HRD selection screen displayed.");
327                var vm = new HrdViewModel(message, idps);
328                return View("HRD", vm);
329            }
330        }
331
332        private string GetRememberHRDCookieValue()
333        {
334            if (Request.Cookies.AllKeys.Contains(_cookieNameRememberHrd))
335            {
336                var cookie = Request.Cookies[_cookieNameRememberHrd];
337                var realm = cookie.Value;
338                var idps = GetVisibleIdentityProviders().Where(x => x.Name == realm);
339                var idp = idps.SingleOrDefault();
340                if (idp == null)
341                {
342                    Tracing.Verbose("Past HRD selection from cookie not found in current HRD list. Past value was: " + realm);
343                    SetRememberHRDCookieValue(null);
344                }
345                return realm;
346            }
347            return null;
348        }
349
350        private void SetRememberHRDCookieValue(string realm)
351        {
352            var cookie = new HttpCookie(_cookieNameRememberHrd);
353            if (String.IsNullOrWhiteSpace(realm))
354            {
355                realm = ".";
356                cookie.Expires = DateTime.UtcNow.AddYears(-1);
357            }
358            else
359            {
360                cookie.Expires = DateTime.Now.AddMonths(1);
361            }
362            cookie.Value = realm;
363            cookie.HttpOnly = true;
364            cookie.Secure = true;
365            cookie.Path = Request.ApplicationPath;
366            Response.Cookies.Add(cookie);
367        }
368
369        [HttpPost]
370        [ValidateAntiForgeryToken]
371        [ActionName("Select")]
372        public ActionResult ProcessHRDSelection(string idp, string originalSigninUrl, bool rememberHRDSelection = false)
373        {
374            Tracing.Verbose("HRD selected: " + idp);
375
376            var uri = new Uri(originalSigninUrl);
377            var message = WSFederationMessage.CreateFromUri(uri);
378            var signinMessage = message as SignInRequestMessage;
379
380            var ip = GetVisibleIdentityProviders().Where(x => x.Name == idp).FirstOrDefault();
381            if (ip == null || signinMessage == null) return View("Error");
382
383            try
384            {
385                if (rememberHRDSelection)
386                {
387                    SetRememberHRDCookieValue(idp);
388                }
389
390                if (ip.Type == IdentityProviderTypes.WSStar)
391                {
392                    signinMessage.HomeRealm = ip.Name;
393                    return RedirectToIdentityProvider(ip, signinMessage);
394                }
395
396                if (ip.Type == IdentityProviderTypes.OAuth2)
397                {
398                    return ProcessOAuth2SignIn(ip, signinMessage);
399                }
400                if (ip.Type == IdentityProviderTypes.Saml2)
401                {
402                    return ProcessSaml2SignIn(ip, signinMessage);
403                }
404            }
405            catch (Exception ex)
406            {
407                Tracing.Error(ex.ToString());
408            }
409
410            return View("Error");
411        }
412
413        private ActionResult ProcessSaml2SignIn(IdentityProvider ip, SignInRequestMessage request)
414        {
415            if (ip.Enabled)
416            {
417                var saml2ProtocolSerializer = new Saml2ProtocolSerializer();
418                var protocolBinding = ProtocolBindings.HttpRedirect;
419                HttpBindingSerializer httpBindingSerializer = new HttpRedirectBindingSerializer(saml2ProtocolSerializer);
420                var authenticationRequest = new AuthenticationRequest()
421                                                {
422                                                    Issuer =
423                                                        new Microsoft.IdentityModel.Tokens.Saml2.Saml2NameIdentifier(request.Realm.TrimEnd('/'), new Uri(ip.WSFederationEndpoint)),
424                                                    Destination = new Uri(ip.WSFederationEndpoint)
425                                                };
426
427                var messageContainer = new MessageContainer(authenticationRequest, new ProtocolEndpoint(protocolBinding, new Uri(ip.WSFederationEndpoint + "/signon.ashx")));
428                var httpMessage = httpBindingSerializer.Serialize(messageContainer);
429                httpBindingSerializer.WriteHttpMessage(new HttpResponseWrapper(System.Web.HttpContext.Current.Response), httpMessage);
430                ControllerContext.HttpContext.ApplicationInstance.CompleteRequest();
431                // return new EmptyResult();
432            }
433            return View("Error");
434        }
435
436        private ActionResult RedirectToIdentityProvider(SignInRequestMessage request)
437        {
438            IdentityProvider idp = null;
439            if (IdentityProviderRepository.TryGet(request.HomeRealm, out idp) && idp.Enabled)
440            {
441                return RedirectToIdentityProvider(idp, request);
442            }
443
444            return View("Error");
445        }
446
447        private ActionResult RedirectToIdentityProvider(IdentityProvider identityProvider, SignInRequestMessage request)
448        {
449            var message = new SignInRequestMessage(new Uri(identityProvider.WSFederationEndpoint), ConfigurationRepository.Global.IssuerUri);
450            SetContextCookie(request.Context, request.Realm, identityProvider.WSFederationEndpoint);
451
452            return new RedirectResult(message.WriteQueryString());
453        }
454
455        private void SetContextCookie(string wctx, string realm, string wsfedEndpoint)
456        {
457            var j = JObject.FromObject(new Context { Wctx = wctx, Realm = realm, WsFedEndpoint = wsfedEndpoint });
458
459            var cookie = new HttpCookie(_cookieContext, j.ToString())
460            {
461                Secure = true,
462                HttpOnly = true,
463                Path = HttpRuntime.AppDomainAppVirtualPath
464            };
465
466            Response.Cookies.Add(cookie);
467        }
468
469        private Context GetContextCookie()
470        {
471            var cookie = Request.Cookies[_cookieContext];
472            if (cookie == null)
473            {
474                throw new InvalidOperationException("cookie");
475            }
476
477            var json = JObject.Parse(HttpUtility.UrlDecode(cookie.Value));
478
479            cookie.Value = "";
480            cookie.Expires = new DateTime(2000, 1, 1);
481            cookie.Path = HttpRuntime.AppDomainAppVirtualPath;
482            Response.SetCookie(cookie);
483
484            return json.ToObject<Context>();
485        }
486
487        internal class Context
488        {
489            public string Wctx { get; set; }
490            public string Realm { get; set; }
491            public string WsFedEndpoint { get; set; }
492        }
493
494        internal class OAuth2Context : Context
495        {
496            public int IdP { get; set; }
497        }
498
499        private void SetOAuthContextCookie(OAuth2Context ctx)
500        {
501            var j = JObject.FromObject(ctx);
502
503            var cookie = new HttpCookie("idsrvoauthcontext", j.ToString());
504            cookie.Secure = true;
505            cookie.HttpOnly = true;
506            cookie.Path = Request.ApplicationPath;
507
508            Response.Cookies.Add(cookie);
509        }
510
511        private OAuth2Context GetOAuthContextCookie()
512        {
513            var cookie = Request.Cookies["idsrvoauthcontext"];
514            if (cookie == null)
515            {
516                throw new InvalidOperationException("cookie");
517            }
518
519            var json = JObject.Parse(HttpUtility.UrlDecode(cookie.Value));
520            var data = json.ToObject<OAuth2Context>();
521
522            var deletecookie = new HttpCookie("idsrvoauthcontext", ".");
523            deletecookie.Secure = true;
524            deletecookie.HttpOnly = true;
525            deletecookie.Path = Request.ApplicationPath;
526            Response.Cookies.Add(deletecookie);
527
528            return data;
529        }
530
531        private ActionResult ProcessOAuth2SignIn(IdentityProvider ip, SignInRequestMessage request)
532        {
533            var ctx = new OAuth2Context
534            {
535                Wctx = request.Context,
536                Realm = request.Realm,
537                IdP = ip.ID
538            };
539            SetOAuthContextCookie(ctx);
540
541            var oauth2 = new OAuth2Client(GetProviderTypeFromOAuthProfileTypes(ip.ProviderType.Value), ip.ClientID, ip.ClientSecret);
542            switch (ip.ProviderType)
543            {
544                case OAuth2ProviderTypes.Google:
545                    return new OAuth2ActionResult(oauth2, ProviderType.Google, null);
546                case OAuth2ProviderTypes.Facebook:
547                    return new OAuth2ActionResult(oauth2, ProviderType.Facebook, null);
548                case OAuth2ProviderTypes.Live:
549                    return new OAuth2ActionResult(oauth2, ProviderType.Live, null);
550            }
551
552            return View("Error");
553        }
554
555        ProviderType GetProviderTypeFromOAuthProfileTypes(OAuth2ProviderTypes type)
556        {
557            switch (type)
558            {
559                case OAuth2ProviderTypes.Facebook: return ProviderType.Facebook;
560                case OAuth2ProviderTypes.Live: return ProviderType.Live;
561                case OAuth2ProviderTypes.Google: return ProviderType.Google;
562                default: throw new Exception("Invalid OAuthProfileTypes");
563            }
564        }
565
566        [HttpGet]
567        public async Task<ActionResult> OAuthTokenCallback()
568        {
569            var ctx = GetOAuthContextCookie();
570            var ip = GetVisibleIdentityProviders().Single(x => x.ID == ctx.IdP);
571
572            var oauth2 = new OAuth2Client(GetProviderTypeFromOAuthProfileTypes(ip.ProviderType.Value), ip.ClientID, ip.ClientSecret);
573            var result = await oauth2.ProcessCallbackAsync();
574            if (result.Error != null) return View("Error");
575
576            var claims = result.Claims.ToList();
577            string[] claimsToRemove = new string[]
578            {
579                "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
580                ClaimTypes.AuthenticationInstant
581            };
582            foreach (var toRemove in claimsToRemove)
583            {
584                var tmp = claims.Find(x => x.Type == toRemove);
585                if (tmp != null) claims.Remove(tmp);
586            }
587            claims.Add(new Claim(Constants.Claims.IdentityProvider, ip.Name, ClaimValueTypes.String, Constants.InternalIssuer));
588            var id = new ClaimsIdentity(claims, "OAuth");
589            var cp = new ClaimsPrincipal(id);
590            return ProcessOAuthResponse(cp, ctx);
591        }
592
593        private ActionResult ProcessOAuthResponse(ClaimsPrincipal principal, Context context)
594        {
595            var message = new SignInRequestMessage(new Uri("http://foo"), context.Realm);
596            message.Context = context.Wctx;
597
598            // issue token and create ws-fed response
599            var wsFedResponse = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(
600                message,
601                principal,
602                TokenServiceConfiguration.Current.CreateSecurityTokenService());
603
604            // set cookie for single-sign-out
605            new SignInSessionsManager(HttpContext, _cookieName, ConfigurationRepository.Global.MaximumTokenLifetime)
606                .SetEndpoint(context.WsFedEndpoint);
607
608            return new WSFederationResult(wsFedResponse, requireSsl: ConfigurationRepository.WSFederation.RequireSslForReplyTo);
609        }
610
611        #endregion
612    }
613}