Bhaskar
Bhaskar

Reputation: 10691

Send ADFS Token From Client to a WCF Service

I have a requirement where-in my Silverlight application needs to connect to a WCF service to fetch data, through an intermediate WCF service, which is hosted in the same domain as the Silverlight. That is, the Silverlight is going to make a call to the Intermediate Service, which will attached the IssuedToken along with the request and send it to the main WCF client. The main WCF service would retrieve the claims from the Thread.Principal.

    var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
    binding.Security.Message.EstablishSecurityContext = false;

    var factory = new ChannelFactory<IMyService>(binding, new EndpointAddress("https://myservice.cloudapp.net:4432/MyService.svc"));
    var channel = factory.CreateChannelActingAs(((ClaimsIdentity)((ClaimsPrincipal)HttpContext.Current.User).Identity).BootstrapToken);

    var data = channel.GetData();

But this code piece fails. I am unable to find property documentation on how to achieve this. Can anyone please help me with this.

Thanks,

Upvotes: 0

Views: 1627

Answers (1)

Daniel M
Daniel M

Reputation: 347

You need to: 1. authenticate opposite the ADFS STS service to obtain a SecurityToken 2. query your service with a channel using "CreateChannelWithIssuedToken", along the lines of:

        var token = GetToken();

        string uri = SERVICE_URL;

        EndpointAddress address = new EndpointAddress(uri);

        var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
        binding.Security.Message.EstablishSecurityContext = false;

        _factory = new ChannelFactory<IService>(binding, address);
        _factory.ConfigureChannelFactory<IService>();
        _factory.Credentials.SupportInteractive = false;

        _service = _factory.CreateChannelWithIssuedToken<IService>(token);

The code for GetToken will look as follows:

    public static SecurityToken GetToken(string username, string password, EndpointAddress federationServiceProxyAddress, EndpointAddress relyingPartyIdentifier)
    {
        var binding = new UserNameWSTrustBinding
        {
            SecurityMode = SecurityMode.TransportWithMessageCredential
        };

        var factory = new WSTrustChannelFactory(binding, federationServiceProxyAddress)
        {
            TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13,
        };

        factory.Credentials.SupportInteractive = false;
        factory.Credentials.UserName.UserName = username;
        factory.Credentials.UserName.Password = password;

        try
        {
            var requestSecurityToken = new RequestSecurityToken
            {
                RequestType = WSTrust13Constants.RequestTypes.Issue,
                AppliesTo = relyingPartyIdentifier
            };

            var channel = factory.CreateChannel();
            return channel.Issue(requestSecurityToken);//, out requestSecurityTokenResponse);
        }
        catch (MessageSecurityException exception)
        {
            // Invalid username or password
            throw new MessageSecurityException(exception.Message, exception);
        }
        catch (Exception exception)
        {
            // Unknown error
            throw new Exception(exception.Message, exception);
        }
        finally
        {
            try
            {
                if (factory.State == CommunicationState.Faulted)
                {
                    factory.Abort();
                }
                else
                {
                    factory.Close();
                }
            }
            catch (Exception) { }
        }
    }

Hope this helps...

Upvotes: 1

Related Questions