0
votes

Running a MVC 4 site on Azure with WIF enabled and using the Wif.SWT dll to use swt tokens from acs.

<microsoft.identityModel>
<service saveBootstrapTokens="true">
  <audienceUris>
    <!--<add value="http://traffictheory.cloudapp.net/" />-->
    <add value="" />
  </audienceUris>
  <issuerNameRegistry type="Microsoft.IdentityModel.Swt.SwtIssuerNameRegistry, Wif.Swt">
    <trustedIssuers>
      <add thumbprint="033F53598E4ED92E51C07238E36BBFF4E67ABAD2" name="https://traffictheory.accesscontrol.windows.net/" />
    </trustedIssuers>
  </issuerNameRegistry>
  <claimsAuthenticationManager type="S_Innovations.TrafficTheory.Web.Security.TrafficTheoryClaimsAuthenticationManager, S-Innovations.TrafficTheory.Web.Security" />
  <federatedAuthentication>
    <cookieHandler requireSsl="false" />
    <wsFederation passiveRedirectEnabled="true" issuer="https://traffictheory.accesscontrol.windows.net/v2/wsfederation" realm="/" reply="/" requireHttps="false" />
  </federatedAuthentication>
  <certificateValidation certificateValidationMode="None" />
  <securityTokenHandlers>
        <add type="Microsoft.IdentityModel.Swt.SwtSecurityTokenHandler, Wif.Swt" />
    </securityTokenHandlers>
    <issuerTokenResolver type="Microsoft.IdentityModel.Swt.SwtIssuerTokenResolver, Wif.Swt" />
  <!--<serviceCertificate>
    <certificateReference findValue="‎417DE8DCA4326B845C189BDE0990673433435524" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
  </serviceCertificate>-->    
</service>

The token that is returned to my client is from

var token = HttpContext.Current.User.BootstrapToken();

and it looks like a htmlencoded query string from what i can tell or a namevalue collection.

I have tried: (client is a httpClient on windows 8 store app)

client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("Bearer", token);

client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("Bearer", System.Net.WebUtility.HtmlDecode(token));

Add("Authorization", string.Format("WRAP access_token=\"{0}\"", token))

and i am out of ideas.

The webapi site do not authenticate the request. FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed is beeing triggeret.

This is what token contains.

http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=HM81Sv2xnRD6P%2bm2W2T%2feBAfAhH2ZTMMxSBBOQ1Rxqs%3d&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=uri%3aWindowsLiveID&Audience=http%3a%2f%2f77.75.160.102%3a48451%2f&ExpiresOn=1348778300&Issuer=https%3a%2f%2ftraffictheory.accesscontrol.windows.net%2f&HMACSHA256=C7D9CvmEeGy1xHXFV3WqPn7L9Zm%2bwoXt8Z8IUf0tgmI%3d

and this is what i have at my client:

http://77.55.160.102:48451/api/federation/end?acsToken=http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=HM81Sv2xnRD6P%2bm2W2T%2feBAfAhH2ZTMMxSBBOQ1Rxqs%3d&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=uri%3aWindowsLiveID&Audience=http%3a%2f%2f77.75.160.102%3a48451%2f&ExpiresOn=1348787731&Issuer=https%3a%2f%2ftraffictheory.accesscontrol.windows.net%2f&HMACSHA256=xZT%2blbcV9WSPaJQ2XdEP5gkNJi6ZIp%2fxGveDAllXU7w%3d

this is what ACS returns to the mvc controller:

wa=wsignin1.0&wresult=%3Ct%3ARequestSecurityTokenResponse+xmlns%3At%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F02%2Ftrust%22%3E%3Ct%3ALifetime%3E%3Cwsu%3ACreated+xmlns%3Awsu%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-utility-1.0.xsd%22%3E2012-09-27T23%3A08%3A11.285Z%3C%2Fwsu%3ACreated%3E%3Cwsu%3AExpires+xmlns%3Awsu%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-utility-1.0.xsd%22%3E2012-09-27T23%3A18%3A11.285Z%3C%2Fwsu%3AExpires%3E%3C%2Ft%3ALifetime%3E%3Cwsp%3AAppliesTo+xmlns%3Awsp%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2004%2F09%2Fpolicy%22%3E%3CEndpointReference+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2005%2F08%2Faddressing%22%3E%3CAddress%3Ehttp%3A%2F%2F77.75.160.102%3A48451%2F%3C%2FAddress%3E%3C%2FEndpointReference%3E%3C%2Fwsp%3AAppliesTo%3E%3Ct%3ARequestedSecurityToken%3E%3Cwsse%3ABinarySecurityToken+wsu%3AId%3D%22uuid%3Acb218b5b-62df-47bc-85d4-0d765c13db39%22+ValueType%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2009%2F11%2Fswt-token-profile-1.0%22+EncodingType%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-soap-message-security-1.0%23Base64Binary%22+xmlns%3Awsu%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-utility-1.0.xsd%22+xmlns%3Awsse%3D%22http%3A%2F%2Fdocs.oasis-open.org%2Fwss%2F2004%2F01%2Foasis-200401-wss-wssecurity-secext-1.0.xsd%22%3EaHR0cCUzYSUyZiUyZnNjaGVtYXMueG1sc29hcC5vcmclMmZ3cyUyZjIwMDUlMmYwNSUyZmlkZW50aXR5JTJmY2xhaW1zJTJmbmFtZWlkZW50aWZpZXI9SE04MVN2MnhuUkQ2UCUyYm0yVzJUJTJmZUJBZkFoSDJaVE1NeFNCQk9RMVJ4cXMlM2QmaHR0cCUzYSUyZiUyZnNjaGVtYXMubWljcm9zb2Z0LmNvbSUyZmFjY2Vzc2NvbnRyb2xzZXJ2aWNlJTJmMjAxMCUyZjA3JTJmY2xhaW1zJTJmaWRlbnRpdHlwcm92aWRlcj11cmklM2FXaW5kb3dzTGl2ZUlEJkF1ZGllbmNlPWh0dHAlM2ElMmYlMmY3Ny43NS4xNjAuMTAyJTNhNDg0NTElMmYmRXhwaXJlc09uPTEzNDg3ODc4OTEmSXNzdWVyPWh0dHBzJTNhJTJmJTJmdHJhZmZpY3RoZW9yeS5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0JTJmJkhNQUNTSEEyNTY9OXB6Uk00UmxsSDZUU091dlNkYktpb0x2UjQzZlhIaTB6OWEzQVZ0dXNHcyUzZA%3D%3D%3C%2Fwsse%3ABinarySecurityToken%3E%3C%2Ft%3ARequestedSecurityToken%3E%3Ct%3ATokenType%3Ehttp%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2009%2F11%2Fswt-token-profile-1.0%3C%2Ft%3ATokenType%3E%3Ct%3ARequestType%3Ehttp%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F02%2Ftrust%2FIssue%3C%2Ft%3ARequestType%3E%3Ct%3AKeyType%3Ehttp%3A%2F%2Fschemas.xmlsoap.org%2Fws%2F2005%2F05%2Fidentity%2FNoProofKey%3C%2Ft%3AKeyType%3E%3C%2Ft%3ARequestSecurityTokenResponse%3E

Update Solution The authentication part of the simpel token.

public static class WebApiConfig { public static void Register(HttpConfiguration config) { GlobalConfiguration.Configuration.MessageHandlers.Add(new OAuthAuthenticationHandler()); // GlobalConfiguration.Configuration.MessageHandlers.Add(new TokenValidationHandler());

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

}

    /// <summary>
    /// Authenticates the ongoing request using Windows Identity Foundation and 
    /// SimpleWebToken (wif.swf). Grabs the token from the header and performs the authentication.
    /// </summary>
public class OAuthAuthenticationHandler : MessageProcessingHandler
{
    ServiceConfiguration _serviceConfiguration;

    public ServiceConfiguration ServiceConfiguration
    {
        get
        {
            if (_serviceConfiguration == null)
                _serviceConfiguration = new ServiceConfiguration();

            if (!_serviceConfiguration.IsInitialized)
                _serviceConfiguration.Initialize();

            return _serviceConfiguration;
        }
    }

    protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            var token = ExtractTokenFromHeader(request);

            if (token != null)
            {
                var identities = ServiceConfiguration.SecurityTokenHandlers.ValidateToken(token);
                var principal = ClaimsPrincipal.CreateFromIdentities(identities);

               // request.SetUserPrincipal(principal);
                Thread.CurrentPrincipal = principal;
                HttpContext.Current.User = principal;
            }
        }
        catch (InvalidSecurityTokenException)
        {
            throw new HttpException((int)System.Net.HttpStatusCode.Unauthorized, "The authorization header was invalid");
        }

        return request;
    }

    protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
    {
        return response;
    }

    static SimpleWebToken ExtractTokenFromHeader(HttpRequestMessage request)
    {
        var authorizationHeader = request.Headers.Authorization;

        if (authorizationHeader != null && authorizationHeader.Scheme == "OAuth")
            return new SimpleWebToken(authorizationHeader.Parameter);

        return null;
    }
}
1
What exactly is your question? Yes, SWT is a token format that will be expressed as a querystring. If you want to send that as a header you can send it as part of the Authorization header as-is or base64 encoded. - woloski
Ohh i forgot the last part of my question, the request ends up in the event of FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed when i try to access the webapi - Poul K. Sørensen
What you scenario looks like? You have a web app and a web api. You configured the web site to use ACS. Who calls the API? - woloski
I have made a WebAPI site, it have both normal and api controllers. It is set up with ACS with SWT tokens. Authentication works fine on the site. Now im doing a windows 8 metro client. It uses the webauthentication broker. The broker asks ACS for a token, this is returned to a post controller on the mysite/api/federation. This controller extract the content of wresult and redirect back to an url which the authentication broker matches. So I now have this token on my client. Problem is that the token is a bootstrapped version (last example in the question above). - Poul K. Sørensen
And I need to put the token into the headers when the client calls the api on mysite/api. - Poul K. Sørensen

1 Answers

1
votes

The WIF SWT package does not handle requests with the Authorization header, it will just configure the SWT handler to be used with the WSFederationAuthenticationModule which understands the WS-Federation protocol. The WS-Fed protocol expects to get a token from a wresult parameter of an HTTP POST. That wresult will have an XML starting with <RequestSecurityTokenResponseCollection> element. Inside that element you will find the SWT security token which is base64 encoded. The token handler of the NuGet package will decode it and validate it and convert that to a ClaimsPrincipal. You will also be able to access that token with the BootstrapToken method as you are doing.

Said that, for the Web API you should handle authentication using a DelegatingHandler and not the WSFederation module because the protocols are different (POST vs GET with a header).

Take a look at this: https://github.com/wadewegner/ValidateACSTokenWebAPI/blob/master/WebAPI/TokenValidationHandler.cs

EDIT: The original question has an alternative implementation, but it is roughly the same approach.