Pass ADFS Token to a Service

2019-02-15 07:50发布

问题:

I have 2 ASP.Net applications: App1 and App2. Both applications are standard web apps that use WIF with the same ADFS server to authenticate the user, but App2 also exposes some WebAPI services.

When the user goes to App1, App1 calls a service on App2 and I need to somehow call the App2 service with the user's token.

If the user, themselves, were calling the service on App2, they would go through the same ADFS authentication and everything would work, but it's App1 that's calling the service on App2, not the user.

Any thoughts on how this might be done?

Thanks!

回答1:

You can use WS-Trust (ActAs) to get a delegation token:

http://weblogs.asp.net/cibrax/archive/2010/01/04/actas-in-ws-trust-1-4.aspx

Or you can do poor man's delegation:

http://www.cloudidentity.com/blog/2013/01/09/using-the-jwt-handler-for-implementing-poor-man-s-delegation-actas/

Or you could use the Thinktecture IdentityServer Adfs Bridge:

http://brockallen.com/2013/04/14/getting-json-web-tokens-jwts-from-adfs-via-thinktecture-identityservers-adfs-integration/



回答2:

I was in the same exact situation and got it all to work. Here's how (I am using Thinktecture Identity Server):

I had to set up a delegation account that my web application uses (webappaccount) to delegate to the realm my service is in by going to Identity Delegation->Add Realm in identity server, and in my web application I had to make a service call to my STS providing the bootstrap token to receive a new security token which I can then use to authenticate to my service.

In the web app config I set:

<system.identityModel>
    <identityConfiguration saveBootstrapContext="true">

and in my web app the code to access my service looks like:

BootstrapContext context = ClaimsPrincipal.Current.Identities.First().BootstrapContext as BootstrapContext;

var factory = new WSTrustChannelFactory(
    new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), _trustUrl);
factory.TrustVersion = TrustVersion.WSTrust13;

factory.Credentials.UserName.UserName = "webappaccount";
factory.Credentials.UserName.Password = "P@ssword";

var rst = new RequestSecurityToken
{
    RequestType = RequestTypes.Issue,
    KeyType = KeyTypes.Bearer,
    AppliesTo = new EndpointReference(_realm),
    ActAs = new SecurityTokenElement(context.SecurityToken)
};

var token = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;

var client = new HttpClient
{
    BaseAddress = _baseAddress
};

client.SetToken("SAML", token.TokenXml.OuterXml);

var response = client.GetAsync("api/values").Result;

My REST service did not require any changes.