Link to home
Start Free TrialLog in
Avatar of sandya_116
sandya_116

asked on

ASP.NET CORE 3.1 - generate bearer token with WS-Federation

I have code similar to the link in https://docs.microsoft.com/en-us/aspnet/core/security/authentication/ws-federation?view=aspnetcore-2.1 to do Single Sign On using WS-Federation. I have code below to generate bearer token for .NET Framework but this code is not working in .NET Core 3.1. Can somebody please help me with similar code for .NET Core? Thank you.

 ClaimsPrincipal claimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
 var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;

System.IdentityModel.Tokens.BootstrapContext context = (System.IdentityModel.Tokens.BootstrapContext)ClaimsPrincipal.Current.Identities.First().BootstrapContext;
SecurityToken token = context.SecurityToken;
if (context.SecurityToken == null)
{
                    var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
                    token = handlers.ReadToken(new XmlTextReader(new StringReader(context.Token)));

}
                GenericXmlSecurityToken xmlTokenOauthToken = (GenericXmlSecurityToken)ProvisionOAuth2SecurityToken(token, PF_IP_STS_Endpoint, appliesToOauth, oauthViaTokenType);
                if (xmlTokenOauthToken != null && xmlTokenOauthToken.TokenXml.HasAttributes)
                {
                    string decodedStr = Encoding.UTF8.GetString(Convert.FromBase64String(xmlTokenOauthToken.TokenXml.InnerText));
                    Dictionary<string, object> values =
                    JsonConvert.DeserializeObject<Dictionary<string, object>>(decodedStr);
                    strToken = values["access_token"] as string;
                    Console.WriteLine(string.Format("BearerToken: Access Token {0} ", strToken));
                }

private static SecurityToken ProvisionOAuth2SecurityToken(SecurityToken foreignToken, string RP_Endpoint, string appliesTo, string localTokeType, string keyType = KeyTypes.Bearer)
        {
            if (String.IsNullOrWhiteSpace(RP_Endpoint)) throw new ArgumentNullException("RP_Endpoint");

            Binding binding = null;

            var WsHttpBinding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
            WsHttpBinding.Security.Message.EstablishSecurityContext = false;
            WsHttpBinding.Security.Message.NegotiateServiceCredential = false;
            WsHttpBinding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
            binding = WsHttpBinding;

            EndpointAddress endpoint = new EndpointAddress(new Uri(RP_Endpoint));

            using (var factory = new WSTrustChannelFactory(binding, endpoint) { TrustVersion = TrustVersion.WSTrust13 })
            {
                factory.Credentials.SupportInteractive = false;
                factory.Credentials.UseIdentityConfiguration = true;

                RequestSecurityToken RST = new RequestSecurityToken()
                {
                    AppliesTo = new EndpointReference(appliesTo),
                    RequestType = RequestTypes.Issue,
                    TokenType = localTokeType,
                    KeyType = null
                };
                RequestSecurityTokenResponse RSTR_OAuthBearerToken;
                IWSTrustChannelContract channel = factory.CreateChannelWithIssuedToken(foreignToken);
                GenericXmlSecurityToken xmltoken = null;
                CancellationTokenSource canceltokensource = new CancellationTokenSource();
                int noofSeconds = 3;
                try
                {
                    string timeoutServiceCallValue = "";
                    if (!string.IsNullOrEmpty(timeoutServiceCallValue))
                    {
                        noofSeconds = Convert.ToInt32(timeoutServiceCallValue);
                    }
                    canceltokensource.CancelAfter(TimeSpan.FromSeconds(noofSeconds));
                    var token = canceltokensource.Token;
                    Task task = Task.Run(() =>
                    {
                        xmltoken = channel.Issue(RST, out RSTR_OAuthBearerToken) as GenericXmlSecurityToken;
                    }, token);
                    task.Wait(token);
                    if ((task.Status == TaskStatus.Faulted || task.Exception != null))
                    {
                        Console.WriteLine("Class1", "Exception occurred while getting OAuth2SecurityToken {0} \n {1} \n {2}", HttpContext.Current.Request.RawUrl, task.Exception.InnerException, task.Exception.StackTrace);
                    }
                }
                catch (TaskCanceledException taskex)
                {
                   
                }
                catch (OperationCanceledException waitex)
                {
                   
                }
                catch (AggregateException aex)
                {
                   
                }
                catch (Exception ex)
                {
                   
                }
                finally
                {
                    canceltokensource.Dispose();
                }
                return xmltoken;
            }
        }
Avatar of Arana (G.P.)
Arana (G.P.)

What about the same page example but selecting 3.1 in the left menu?
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/ws-federation?view=aspnetcore-3.1
Avatar of sandya_116

ASKER

What I meant to say is I followed that article for SSO and that is working fine in ASP.NET Core 3.1. The part where I am stuck is at getting the Bearer token. The code I have pasted is sample code that worked for .NET Framework 4.8 but I need similar code for .NET Core 3.1. Thanks.
1)  Generate a public / private key from here:  https://travistidwell.com/jsencrypt/demo/

On the service side:
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using ThirdParty.BouncyCastle.OpenSsl;


   //read the private key file location
  using (TextReader stream = System.IO.File.OpenText(PRIVATEKEYLOCATION))
                    {
                       // read the private keyfile
                        var reader = new PemReader(stream);
                        //get the key
                        var key = new RsaSecurityKey(reader.ReadPrivatekey());

 
                     //issue claims, which can be adjusted
                        var claims = new List<Claim>()
                        {
                            new Claim(ClaimTypes.Name, user.FirstName),
                            new Claim(ClaimTypes.GivenName, user.LastName),
                            new Claim(ClaimTypes.WindowsAccountName, user.Username),
                            new Claim("DisplayName", (user.FirstName ?? string.Empty) + " " + (user.LastName ?? string.Empty)),
                            new Claim(ClaimTypes.Email, user.Email)

                        };

                    //create the token
                        var token = new SecurityTokenDescriptor()
                        {
                            Expires = DateTime.UtcNow.AddMinutes(timeout_min),
                            Issuer = issuer_URL,
                            Audience = audience_URL,
                            Subject = new ClaimsIdentity(claims),
                            Claims = claims.ToDictionary(group => group.Type, group => (object)group.Value),
                            IssuedAt = now,
                            SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256)
                        };


                        var tokenHandler = new JwtSecurityTokenHandler();
                        //sign the token
                        string token =  tokenHandler.CreateEncodedJwt(token);

                       //token can now be returned to the client

Open in new window

This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.