-1

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;
    }
}
Poul K. Sørensen
  • 16,950
  • 21
  • 126
  • 283
  • 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 Sep 27 '12 at 22:33
  • 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 Sep 27 '12 at 22:35
  • 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 Sep 27 '12 at 22:59
  • 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 Sep 27 '12 at 23:04
  • And I need to put the token into the headers when the client calls the api on mysite/api. – Poul K. Sørensen Sep 27 '12 at 23:04
  • Looking at the edits I just made. It looks abit like the bootstraped token is key/value without the xml. So maybe i need to create the xml syntax at the client again? – Poul K. Sørensen Sep 27 '12 at 23:10
  • Could anyone tell me where I can find tutorial on this subject? I am very confused. –  Sep 10 '17 at 04:17

1 Answers1

1

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.

woloski
  • 2,863
  • 16
  • 14
  • string authHeader = request.Headers.GetValues("Authorization").First(); exception: System.InvalidOperationException: The given header was not found. – Poul K. Sørensen Sep 28 '12 at 06:54
  • Does this mean the api cant be accessed by the normal authentication if i add this ? or will both work. – Poul K. Sørensen Sep 28 '12 at 06:55
  • things start to work. Both authentications work against the api. One issue now is that the bootstrapped token do not have other claims than nameidentifier and provider. this means i cant do[Authorize(Roles="BLALABLA")] – Poul K. Sørensen Sep 28 '12 at 07:07
  • If you are using LiveID you will only get nameidentifier which is an opaque id, but nothing else. You can try with Google which gives you the email of the user. But that might deserve its own question. Please mark this as answered if you think it helped. – woloski Sep 28 '12 at 14:01
  • I know, but i have added roles and claims upon the authentication my self. They are not included in the bootstrap token. – Poul K. Sørensen Sep 28 '12 at 15:46
  • How and where did you add them? In ACS? Are you hardcoding them? – woloski Sep 28 '12 at 16:29
  • They are added in the FederatedAuthentication.WSFederationAuthenticationModule for the SecurityTokenValidated event. When the controller returns the bootstrapped token i can see the claims in the identity, so i know they are there. – Poul K. Sørensen Sep 28 '12 at 18:34
  • IClaimsIdentity claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity; token = claimsIdentity.BootstrapToken.ToString(); This is how the bootstraptoken is made. So it might be that the bootstrap token is generated earlier ? – Poul K. Sørensen Sep 28 '12 at 18:36
  • 1
    The bootstrap token is the original token as it was posted to your website and won't have the claims you are adding on that event. If they were part of ACS rules then the bootstrap token would have them. If you are adding claims to that token, you have to re-sign, otherwise there is no point of being a Security Token. In essence, you might want to generate your own version of the token with augmented claims and sign it with the same symmetric key. – woloski Sep 28 '12 at 18:52
  • 1
    The token handler has a WriteToken that would allow you to do that. In your "end" action you would have to recrate the token based on the bootstrap token and return that new token. – woloski Sep 28 '12 at 18:52
  • BTW, this should have gone to a separate question – woloski Sep 28 '12 at 18:53
  • Okay, guess i will wrap it up here then. I moved it to http://stackoverflow.com/questions/12646216/how-to-generate-a-new-bootstraptoken-with-added-claims-for-swt-client if you care to share – Poul K. Sørensen Sep 28 '12 at 19:32