C# external web service requires timestamp - c#

Your help is much appreciated.
I am trying to automate a web service call using C#. I managed to get it working from SoapUI. The service call requires authentication with valid username/pw as well as timestamp. But I don't know how to add this timestamp to C# service call.
Details of the web service.
URL: https://prod.decisionpoint3.com/fleet/bsm/api/JobExecutionService?WSDL
Authorization Basic
Credentials. Username:xxxx, Password:xxxx
In SoapUI, under Outgoing WS-Security Configurations, Add Username using the credential above and then add Timestamp, with Time to Live as 60
Details of request from SoapUI
request - getJobExecutions, raw XML as below
To Automate I created a C# Console application, added web reference as Veda. Code snippet as below
string username="xxxx";
string password="xxxx";
Veda.JobExecutionServiceImplService service = new Veda.JobExecutionServiceImplService();
System.Net.NetworkCredential credential=new NetworkCredential(username,password);
service.Credentials=credential;
service.Timeout = 1000;
Veda.JobDefinitionKey jobDefinitionKey=new Veda.JobDefinitionKey();
jobDefinitionKey.jobName="xxxx";
jobDefinitionKey.serviceFQN="Enterprise/Consumer/Term/ConsumerTermBusinessService";
jobDefinitionKey.templateName="ConsumerTermAUDataExtractCRM";
Veda.executionDateTimeRange executionDateTimeRange = new Veda.executionDateTimeRange();
executionDateTimeRange.startSpecified = false;
executionDateTimeRange.endSpecified = false;
Veda.JobExecution[] executions=service.getJobExecutions(jobDefinitionKey, executionDateTimeRange);
foreach(var exe in executions)
{
Console.WriteLine(exe.id);
}
My code threw an Service Access Violation exception because of this missing timestamp information.
your help in pointing the direction is much appreciated.

Related

C# Swagger generated client with domain authentication

We have a simple rest API exposed with Swagger UI. We usually copy-paste the raw definition to editor.swagger.io, and generate a C# client. The generated code works very well - but we work in a Windows AD environment, and we cannot find any way to tell the client to use the current user credentials during the communication. So the IIS hosted rest API throws Unauthorized exception - as it is set to Windows authentication mode.
Is it possible to use the generated client this way? Any option to add to the API definition to generate such a client?
Writing a client manually is easy:
var client = new WebClient();
client.UseDefaultCredentials = true;
...
but we would like to generate it ... but the Configuration contains nothing about credentials ... :(
public static IO.Swagger.Api.IBookingApi GetBookingApiWebApi()
{
var basePath = ConfigurationManager.AppSettings["web.api.url"];
var api = new BookingApi(basePath);
return api;
}
Thanks in advance...

How to access NiFi using proxy user request

I want to access NiFi and do some actions through external web application created in C# using proxy user request. For that,
I have created C# web application and hosted as secure connection(https).
I need to access NiFi components using its REST API service without authorization token. Added C# web application certificate into NiFi truststore and added certificate name as user (CN=machineName) in NiFi. Also, added "proxy user request" policy for the newly added user.
In C# web application, added "X-ProxiedEntitiesChain = <username>" in header while requesting NiFi API. But it returns "unknown user" error in response. Please find the sample code below,
var httpWebReq=(HttpWebRequest)WebRequest.Create("https://testhost:8080/nifi-api/access");
httpWebReq.Headers["X-ProxiedEntitiesChain"] = "<username>";
httpWebReq.Method = "GET";
var response = (HttpWebResponse)httpWebReq.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return responseString;
Based on the available information the most likely problem is that you are not using a properly authorized user.
Check that you are using the proper username, and confirm that it is actually authorized for access.
(And of course make sure you don't just pass the string "username")

How do I setup a valid on-premise ADFS URI?

I have a .NET 4.6.2 Windows client application which needs to get an authentication token from our on-premise ADFS server and use it to call an ASP.NET Core REST API. It's client name, id (GUID) and re-direct URI have been registered with ADFS. I am using the latest ADAL (v3.13) library to facilitate the authentication. I am attempting to get a token as demonstrated in the ADAL sample code like this:
AuthenticationContext authenticationContext = new AuthenticationContext("https://<adfs-sts-server>/<rest-api-host>", false);
var result = authenticationContext.AcquireTokenAsync(<rest-api-resource-uri>, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
The AcquireTokenAsync call returns an error, saying: The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
Can anyone tell me:
Is the "requested URI" refered to in the error the https://<adfs-sts-server>/<rest-api-host> or <rest-api-resource-uri>?
Do I need to register <rest-api-host> or <rest-api-resource-uri> with ADFS in some way, and if so how?
Any other information I need to get this to work?
Thanks!
Peter
Using Active Directory Federation Services (ADFS) to provide authentication for on-premise endpoints from a Windows Client
Configuring ADFS
There are 2 parts to configuring ADFS.
Register the client application with ADFS
ADFS needs to be able to identify the application requesting user authentication, whether it be a service, WPF application, Web client or Office Add-in. I have gone generic and added the following client, which we can use for most of our C# requests; we may need to register a new client with different callback for Web clients.
Use one of the many tools out there to generate a GUID for the client ID.
* CLIENT_ID and APP_NAME should be unique.
* For a web client the redirect URI is where the auth service will redirect your call after authenticating the user. It should be an endpoint where you can process the token and continue with your client application. The redirect URI is not really used with rich clients/services/add-ins.
CLIENT_ID = 26E54EC9-7988-4DAE-A527-483A8A78B1C6
APP_NAME = Investplus
DESCRIPTION = Invest+ rich client suite
REDIRECT_URI = https://server/redirect-adfs.html
Instructions for Client registration
(may be possible in a wizard, but this is what I found on the web and it worked fo us)
Log on to the AD FS server as administrator and open a Windows PowerShell command window.
Enter the following command. In Windows PowerShell
Add-AdfsClient -ClientId <CLIENT_ID> -Name <APP_NAME> -RedirectUri <REDIRECT_URI>
Register the resource to be accessed ('Relying Party' in ADFS speak)
I found this link useful, it takes you through the steps of the wizard for setting up a relying party.
Instructions for Relying Party registration
The administrator on the server team will need to use the ADFS Add Relying Party Trust Wizard, and under the "Select Data Source" step select Enter data about the relying party manually.
Values you need to supply for this wizard:
DISPLAY_NAME = "MyInvestApi" (Unique display name for this Relying party)
PROFILE = "AD FS Profile"
ENABLE_SUPPORT_FOR_WS-FEDERATION_PASSIVE_PROTOCOL = true
URL = "https://server/api" (Unique URL for this RP)
ADD_ONE_OR_MORE_IDENTIFIERS = eg. "urn:myInvestApi" and "https://server/api"
ACCEPT_REMAINING_DEFAULTS
when given the opportunity, Add Claim Rules:
SEND_LDAP_ATTRIBUTES_AS_CLAIMS = true
ATTRIBUTE_STORE = Active Directory
SELECT_USEFUL_ATTRIBUTES = User-Principal-Name; Email; Display-Name
Configuring/Coding the Client application
Microsoft provides Active Directory Authentication Libraries (ADAL) for a range of platforms and languages from C# to Javascript, and from iOS to Cordova to Node.
The API exposed has changed significantly in each major version: I am using the latest C# library, currently 3.13.5.
The library makes the coding very simple, just a few lines; where I had problems was:
I couldn't find an explanation of what URL to use for the ADFS
Secure Token Service (STS)
I couldn't find documentation of the whole process as I am doing here (most documentation focussed on Azure FS), I struggled to work out
how the values provided to ADFS for Client and Relying party mapped
to the values used in the code.
What is the ADFS endpoint/URL to use in code?
Microsoft's best practice is to name your ADFS/STS server URL https://sts.domain.com (some people use https://adfs.domain.com, ask your server admins). However, if you try to hit this from a browser you'll get a 404 - Not found and trying to retrieve a token in the code, the ADAL library reports:
The browser based authentication dialog failed to complete. Reason: The server has not found anything matching the requested URI (Uniform Resource Identifier).
This is how I found the endpoint to use:
ADFS pubishes federation metadata at 'https://sts.domain.com/federationmetadata/2007-06/federationmetadata.xml'
Extract this file and open in a text editor.
When configuring the Relying Party, we specified "Enable Support for WS-Federation Passive Protocol" when specifying our resource endpoint, so search the XML for PassiveRequestorEndpoint.
Use the <Address> from this node - in my case https://sts.domain.com/adfs/ls/. I don't know if this will always be the value, or if it is specified when ADFS is setup and therefore potentially different per site.
What other values to use in the code?
We want our client app to retrieve a JSON Web Token (JWT) from ADFS which we can pass to our protected resource for authentication/authorization purposes.
At its most simple, the access token can be retrieved in 3 lines of code + configuration, and this will show how to translate what we have configured in ADFS to the values required by ADAL:
var stsEndpoint = "https://sts.domain.com/adfs/ls/";
var relyingPartyIdentifier = "urn:myInvestApi"; // Tenant in Azure AD speak, but this is an on-premise service
var authority = stsEndpoint + relyingPartyIdentifier;
var restResourceUrl = "https://server/api";
var redirectUri = "https://server/redirect-adfs.html";
const string CLIENT_ID = "26E54EC9-7988-4DAE-A527-483A8A78B1C6";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
var asyncRequest = authenticationContext.AcquireTokenAsync(restResourceUrl, CLIENT_ID, redirectUri, new PlatformParameters(PromptBehavior.Auto));
var accessToken = asyncRequest.Result.AccessToken;
Useful references
ASP.NET Core Token Authentication Guide
ADAL - Native App to REST service - Authentication with ACS via Browser Dialog
Create a line-of-business Azure app with AD FS authentication
OAuth 2 Simplified
To issue the token for the web API, we need to make the ADFS to aware it by creating a relying party trust for the web API. And when we add a replying party we need to specify the identifiers for the replying party like figure below(Windows Server 2012 R2):
Then we can use this identifiers as the resource URI to acquire the token for this replying party. Please ensure that the resource URI is correct as you config like figure above.
And here is an article about developing with ADFS using OAuth:
Developing Modern Applications using OAuth and Active Directory Federation Services
Depending on the version of asdf, you may be able to use 'discovery' to obtain the endpoints to use.
Have a look at this post for more details: http://www.cloudidentity.com/blog/2015/08/21/openid-connect-web-sign-on-with-adfs-in-windows-server-2016-tp3/

WCF self hosted HTTPS with custom UserNamePasswordValidator

I have a WCF service which is running fine.
It is used within an intranet network.
It is a self-hosted service
(no IIS) managed by a simple Windows Form program.
It is used by a
WCF client (WPF C#).
I now need to add security to it and after having read a lot of posts on the internet I'm getting confused as there are many ways of doing.
I need a custom username and password validator (I will have to call another web service to know if user is authorized or not).
I also need secure communication between client and server.
I am currently using basicHttpBinding.
MS recommends the use of NetTcpBinding in my case (https://msdn.microsoft.com/en-us/library/ff648863.aspx#TransportSecurityWCF), but I am not sure if this is or can be secured ?
I think I better use WsHttpBinding to have SSL: do you think that this link provides proper solution to my case ? https://msdn.microsoft.com/en-us/library/ms733775.aspx ?
Thanks for your advices
You can do SSL/Transport encryption with BasicHTTPBinding. That doesn't need to change; you just need to set up the host side with "Transport" security, add some code and a certificate, and you should be able to proceed without changing too much code. I can include a small code sample below, since I did the same thing you're trying to do via a self-hosted service.
BasicHttpBinding b = default(BasicHttpBinding);
if (bUseSSL) {
//check for ssl msg credential bypass
if (bSSLMsgCredentialBypass) {
b = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
} else {
b = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
}
b.TransferMode = TransferMode.Buffered;
b.MaxReceivedMessageSize = int.MaxValue;
b.MessageEncoding = WSMessageEncoding.Text;
b.TextEncoding = System.Text.Encoding.UTF8;
b.BypassProxyOnLocal = false;
//b.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
}
The authentication/authorization can be done, too, without changing what you currently have. You really have two choices:
One is that you create a Login function that get's called when the client first visits the host. You then send some token value back to the client for all subsequent communications.
The other way involves creating that custom authentication check, using the message inspector functionality found in Dispatcher.IDispatchMessageInspector and a public function called AfterReceiveRequest. Within that function, you can examine the UserID and Pwd (from within the HTTP header data) sent from the clients- but you need to implement this on both the client and host sides, otherwise it doesn't work.

Setting ClientCredentials: getting "Username is not provided" error

I'm tasked with creating a WCF service from a local wsdl file. I have done some R&D on this task. I have added a web reference of that local wsdl file. Now I want to create a client for this service in order access the service.
How do I provide the username and password in the client?
Currently, when I am accessing the service methods in the client I get an error:
Username is not provided.
Here's the relevant code:
ServiceGetProductFeeds.ProductFeedServiceClient SerProdFeeds = new ServiceGetProductFeeds.ProductFeedServiceClient();
SerProdFeeds.ClientCredentials.UserName.UserName = "XXXXXX";
SerProdFeeds.ClientCredentials.UserName.Password = "*******";
SerProdFeeds.getProductFeed();
Any tips on what's not correct with the above code?
Do you have security mode, clientCredentialtype configured appropriately in your configuration files? Here is a blog post that very closely matches your question. I hope this helps!
http://amadotech.blogspot.com/2009/11/error-username-is-not-provided-specify.html
Actually there're three causes with my application:
Security mode was not appropriae.
Client credential type was not appropriate.
The call missed passing the required Username and password.

Categories

Resources