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;
}
}
The WIF SWT package does not handle requests with the Authorization header, it will just configure the SWT handler to be used with the
WSFederationAuthenticationModulewhich understands the WS-Federation protocol. The WS-Fed protocol expects to get a token from awresultparameter of an HTTP POST. Thatwresultwill 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 aClaimsPrincipal. You will also be able to access that token with theBootstrapTokenmethod as you are doing.Said that, for the Web API you should handle authentication using a
DelegatingHandlerand 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.