I want to use ACS as a STS for the service bus. I've managed to use ACS for authentication for a web service. However, the service bus requires a token and I don't know how to retrieve such from the ACS?
In short, I want my client wcf services to be able to use the service bus by authenticating with certificates that matches certificates stored as service identities in the acs (the one corresponding to the service bus -sb).
Also, I'm using NetTcpRelayBinding for the Service Bus.
I guess I can use a token from acs if I can just retrieve it using the client certificate...?
Getting a token from ACS using client certificate credentials over WCF is a well supported scenario.
There is an ACS sample that does WCF client certificate auth available here, look for Acs2CertificateBindingSample. Points of interest are how to create the binding that obtains a token from ACS:
public static Binding CreateServiceBinding(string acsCertificateEndpoint)
{
return new IssuedTokenWSTrustBinding(CreateAcsCertificateBinding(), new EndpointAddress(acsCertificateEndpoint));
}
public static Binding CreateAcsCertificateBinding()
{
return new CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential);
}
And how to create the channel factory using this binding, and how to specify your client certificate credential:
ChannelFactory<IStringService> stringServiceFactory = new ChannelFactory<IStringService>(Bindings.CreateServiceBinding(acsCertificateEndpoint), serviceEndpointAddress);
// Set the service credentials and disable certificate validation to work with sample certificates
stringServiceFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
stringServiceFactory.Credentials.ServiceCertificate.DefaultCertificate = GetServiceCertificate();
// Set the client credentials.
stringServiceFactory.Credentials.ClientCertificate.Certificate = GetClientCertificateWithPrivateKey();
The sample is not using service bus, just a simple "IStringService" interface, but if you incorporateyour NetTcpRelayBinding into the binding composition, the same mechanisms should be applicable to your scenario.
Related
Currently working with WSO2 API Manager version 2.2.0. It is very good with implementation of OAuth 2.0.
When we define a new Application through WSO2 API Store, we are able to generate Consumer Key and Secret and select Grant Type to generate Access Token. After that we should subscribe to APIs with some Subscription Tier.
Access Token (also called API Key) is then authorized during API call. The Access Token is linked to attributes which are then put into AuthenticationContext, like the following extract from the org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.java:
APIKeyValidationInfoDTO info;
info = keyValidator.getKeyValidationInfo(apiContext, apiKey, apiVersion, authenticationScheme, clientDomain,
matchingResource, httpMethod, defaultVersionInvoked);
if (info.isAuthorized()) {
AuthenticationContext authContext = new AuthenticationContext();
authContext.setAuthenticated(true);
authContext.setTier(info.getTier());
authContext.setApiKey(apiKey);
authContext.setKeyType(info.getType());
authContext.setUsername(info.getEndUserName());
authContext.setCallerToken(info.getEndUserToken());
authContext.setApplicationId(info.getApplicationId());
authContext.setApplicationName(info.getApplicationName());
authContext.setApplicationTier(info.getApplicationTier());
authContext.setSubscriber(info.getSubscriber());
authContext.setConsumerKey(info.getConsumerKey());
APISecurityUtils.setAuthenticationContext(synCtx, authContext, securityContextHeader);
This is working perfectly, but now, I would like to have my own custom authentication handler, which is not based on Access Token, but rather X.509 certificates where CN would be my identification of enitity (Writing Custom Handlers).
And also, I would like to have the benefit of Application settings and Subscription Tiers in order to manage such attributes for different entities calling the APIs using X.509 certificate. Using the above mentioned call it is not working because I do not have any apiKey.
I'm trying to find a way how to get Application API data with identification from X.509 certificate instead of Access Token to set the Subscription Tier and other AuthenticationContext attributes.
Any suggestions it can be done?
There is no way you can find subscription or application details without a token unless you're sending that information with the request itself. Without a token, you can only know what the API is, but you don't know what the app is.
These attributes are required, because they are used for application and subscription level throttling in throttle handler.
What you can do is set some attribute like commonNameAtribute(CN) in the certificate as the application name , client ip(get from messageContext) as the the application ID. So the application level throttling will work, without having to create an application in store. Set Application tier as any one of the avialble available application tiers in the store.
Set consumer key as null, set subscriber also as commonNameAtribute.
And you can override the DefaultKeyValidationHandler in order to skip the subscription validation. This class can be configured in api-manager.xml
a WCF Service in hosted in our internal server. an external client will consume it and, our Service will consume our SharePoint service in order to edit an item list.
The WCF Service will have the automatically earn the windows authentication to access to the SharePoint site so I do not have to provide a login and password not domain name.
I am not sure how I am supposed to code my service:
NetworkCredential credential = CredentialCache.DefaultNetworkCredentials;
will be enough?
Architecture
But if you do need to use a specific account you could go for the following:
NetworkCredential credentials = new System.Net.NetworkCredential("name", "password", "optional:domain");
IMO, it should be enough, if your wcf and SharePoint services in same (or trusted) domains, and you select appropriative security mode.
See for more details:
http://msdn.microsoft.com/en-us/library/ms733836.aspx
Following this post I have created a WCF client which:
Uses ADFS to authenticate users against AD.
Provides a SAML2 ticket to the caller.
Uses the supplied SAML2 ticket to call the WCF Service.
This is working great, however the next part of my problem is to extend this to use Azure ACS.
I added the RP to ACS, and changed the STS reference to point to ACS using Add STS Reference in Visual studio.
I have extended the Token.GetToken method, supplying the token into the following method:
public static SecurityToken GetToken(SecurityToken adfsToken, string appliesTo, string idpEndpointAddress, out RequestSecurityTokenResponse rsts)
{
WS2007HttpBinding binding = new WS2007HttpBinding();
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress(idpEndpointAddress));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.ConfigureChannelFactory();
// Create issuance issuance and get security token
RequestSecurityToken requestToken = new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue);
requestToken.AppliesTo = new EndpointAddress(appliesTo);
WSTrustChannel tokenClient = (WSTrustChannel)trustChannelFactory.CreateChannelWithIssuedToken(adfsToken);
SecurityToken token = tokenClient.Issue(requestToken, out rsts);
return token;
}
To the following endpoint:
https://test.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric
But I get the following exception:
Secure channel cannot be opened because security negotiation with the
remote endpoint has failed. This may be due to absent or incorrectly
specified EndpointIdentity in the EndpointAddress used to create the
channel. Please verify the EndpointIdentity specified or implied by
the EndpointAddress correctly identifies the remote endpoint.
With an inner exception of:
ACS10001: An error occurred while processing the SOAP header.
What do I need to configure in ACS to get this working with the token supplied by ADFS?
Do I need to use the token supplied by ACS, or can I use the one supplied by ADFS in the service? (It appears to be working..)
Take a look at the linked ACS sample, which seems to be doing exactly what you're asking.
I have a web app that calls a WCF web application with several services, all using basicHttBinding, on different servers (web server, app server and database server). One of the services has to connect to a database that must be called using an active directory account. Coming in from the web site the user is anonymous.
I have been given credentials to set this user to but I cannot get it to work. I create my channel on the web server like this:
ChannelFactory<T> channelFactory = GetChannelFactoryFromPool<T>(enpointAddress);
channelFactory.Credentials.Windows.ClientCredential.UserName = username;
channelFactory.Credentials.Windows.ClientCredential.Password = password;
channelFactory.Credentials.Windows.ClientCredential.Domain = domain;
proxy = channelFactory.CreateChannel();
In the service on the app server I am trying to determine if the credentials are correct by doing this:
var ssc = ServiceSecurityContext.Current;
but ssc is always null. Can this be done with basicHttpBinding?
Thanks,
Paul
The basicHttpBinding does support Windows authentication as documented in this good MSDN article. You also need to ensure the service operations are configured to allow impersonation of the client credentials to have the security context populated as expected.
In our organization we are trying to use EWS Managed API to access mailboxes from a custom UI client on Exchange 2010. We have a .NET 4.0 WCF service running on IIS 7.5 calling the EWS methods on behalf of the UI client. Client and WCF service communicate over https, so does the WCF service and EWS. We now want to create service accounts (basically AD accounts with impersonation rights on certain email inboxes) and run the WCF service under these service accounts. However, when I run the WCF service under a particular AD user in IIS (Anonymous authentication enabled with Anonymous user identity set to the specific AD user), EWS throws a 401 Unauthorized exception. Upon examining the ExchangeService object, the Credentials object is null. If I hardcode the credentials, the service can access EWS. Below is the code that I am using to create the ExchangeService object.
var service = new ExchangeService(ExchangeVersion.Exchange2010)
{
Url = new Uri(ConfigurationManager.AppSettings["EWSUrl"]),
// If I uncomment the below line, the service can access EWS. However, I want the user under which the service is running to access EWS.
//Credentials = new NetworkCredential("ImpersonatingUser", "secretPwd", "TESTDOMAIN"),
ImpersonatedUserId = new ImpersonatedUserId { Id = emailAddress, IdType = ConnectingIdType.SmtpAddress },
};
I read somewhere that the System.ServiceModel.ServiceSecurityContext.Current.WindowsIdentity object will have the current user under which the service is running. However, the System.ServiceModel.ServiceSecurityContext.Current context is null in my case.
How do I get the service account's credentials (without hardcoding it in the code) and pass it to EWS? Please let me know if you need more details.
Edit: In IIS 7.5, I have created a separate app pool running under the impersonating AD user's identity, and configured my WCF service to run in this app pool. Still can't get the service credentials.
Thanks in advance.
Unless your WebService runs on the Exchange box, you'll need to configure Kerberos. NTLM does not allow credential delegation.
Another option is to switch to Basic authentication secured with SSL. But this means to loose single sign on in your client application.