Verify that a valid session token exists before making a WCF service call multiple browsers with shared session - wcf

Using WIF, WCF within a Silverlight client accessing backend WCF services.
The application sign out uses Federation Authentication Module SignOut method which in turn calls Session Authentication Module (SAM) DeleteSessionTokenCookie for the local RP (Relying Party) sign out. A sign out to the the IP (Issuing Party) is subsequently called. All of this functions as expected.
I have come across the following multiple browser scenario relating to shared session that results in a “remote server returned an error not found” issue. If IE's "New Session" is used this is not an issue.
Steps:
Use IE shortcut to open a browser instance 1, navigate to application and login.
Use IE shortcut to open a browser instance 2, navigate to application and login.
Log out of application in browser instance 2.
Perform any operation that requires communication to the server. e.g. Log out of application browser instance 1.
Result: “remote server returned an error not found” exception
Is it possible to detect that the WIF token has been deleted prior to making a WCF call in browser instance 1 and so notify the user. The IdentityModelServiceAuthorizationManager.CheckAccessCore (OperationContext) method is being used to verify service access (authorization) prior to making any WCF service calls. Would it be possible to access and evaluate session token related information at this time? Or is there another approach that can be used?

Related

Connect to Azure to create an Application registration

I'm trying to write a C# console app that will register an application in Azure Active Directory. It should work just as the web application project creation wizard in VS 2013 when you Change Authentication and select Organizational Accounts in Azure.
Following the fiddler trace, I can see that it authenticates the user using wsfederation and an oauth2 token and then uses the graph.windows.net graph api to configuration the AAD directoryObjects service principal and application.
I have tried to use the sample Graph API app, but it requires the app be registered first so that I have the clientId (application id) and password (key) to send in the Acquire Token request using the Windows Azure AD Authentication Library for .NET.
I've tried using a bunch of the different Azure APIs but they all have my chicken and egg problem, I want to use an unregistered client application to register an application in AAD. I need to avoid Configuring Application Authentication and Authorization for the Graph API so that the user has no manual steps.
Does anyone know how Visual Studio does it, using just the user login with browser prompt or if there is a standard application id and password that can be used to access the graph API, like there is the standard login URL, https://login.windows.net/common? Some C# samples would be greatly appreciated.
This post does the Application creation, but requires a clientId and password, which I don't think I have.
You can't register a new application using the Graph API from an unregistered client. The only reason the VS2013 flow works is because VS2013 is already registered in a special way within Azure AD -- it's a first party application and has unique permissions. In my Fiddler trace, VS2013 uses a client ID of 872cd9fa-d31f-45e0-9eab-6e460a02d1f1. Technically you can use this client ID and the redirect URI of VS2013 to initiate sign-on with Azure AD. This still involves user interaction (the user has to authenticate via browser pop-up) so it doesn't meet your requirement for "no manual steps," but it's somewhat helpful for understanding the protocol flows and how registration works.
The bottom line is that if you want to call the Graph API without user interaction (client credential flow), the client needs to be registered with the proper application permissions.

With OWIN/OAuth2, calling GET prevents Windows identity from arriving with subsequent POSTs to the token endpoint

In what seems like an elementary scenario, calling a GET method in my OAuth2/OWIN-protected server prevents the server from receiving the Windows identity on subsequent POSTS to the /token endpoint. What am I doing wrong?
This is a Web API service that includes an embedded OAuth2 authorization server and Microsoft's OWIN pipeline.
The authorization server provider inherits from OAuthAuthorizationServerProvider, and is installed in my Startup class. It overrides both GrantResourceOwnerCredentials (for username/password authentication) and GrantClientCredentials (for the client_credentials grant_type).
Here's the problem. If I configure the service for Windows authentication the following ensues.
Client POSTS to my /token endpoint to get a token.
Client's Windows identity arrives at the server in the GrantClientCredentials method's context parameter (specifically, context.Request.User). I can give him an appropriate token using context.Validated(id), where id is a ClaimsIdentity appropriate to his credentials.
Let's say client even POSTS again to get another token. Again, his credentials come to the server in context.Request.User. All is well.
Client does a GET to my API endpoint, including the token.
Server can inspect the claims in the token. All is still well.
Either the same client or a different client POSTs to get another token.
This time, context.Request.User arrives as null. PROBLEM!!!
If I restart the server, everything is set right. Restarting the browser does not help.
These symptoms happen whether running with IIS Express or real IIS.
The problem exists only for Windows authentication. When Anonymous authentication is turned on and a username/password duo passed, the credentials arrive safely in step 7.
FWIW, I have not yet programmed anything pertaining to a client_id or "secret". Still working on figuring that part out. If that's the problem, I'd appreciate help in how to issue a client_id and secret.

WCF Windows authentication + Console apps on server

I have following setup:
WPF client calls WCF SerivceA. Here I have windows authentication with Basic HTTP Binding.
The SerivceA will invoke one batch file (.bat or you can say .exe file) from one UNC path. This works. Batch and thus exe called inside it executes.
The executed exe now calls to ServiceB. Here, it fails. The error is:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate'.
This seems that exectued exe fails to pass the AD user account. It passes following:
IIS APPPOOL\user1 which is not AD user and that is why it fails.
To solve this, I tried impersonation at ServiceA, so I can invoke the batch file under caller's credentials. But no luck. I also tried delegation as well.
What is the issue here?
You didn't explain from which IPrincipal you did the delegation or impersonation, but you can only use delegation if the server is correclty configured for it, otherwise it will only accept the least priviledge account that performed the request.
I ended up creating a specific user for IIS and registred it for application pool. So now by default, such operations are done under this users's identity and everything works fine.

Authenticate a call to a WCF service

I am trying to call a Sharepoint Web Service via WCF from inside a .ASHX on a different server. My code works if I run inside of Visual Studio's debug web server, but not from IIS. The working server works in various authentication modes (Kerberos, NTLM), and the non-working one doesn't work in any. I am impersonating the same user in both cases.
Using NTLM, I recorded a working session and non-working session in Wireshark. In the working one, Wireshark parses the NTLM data and reports a DOMAIN and USER NAME that I expect. In the non-working one, it shows
DOMAIN: NULL
USER NAME: NULL
I have debugged in IIS and impersonation is definitely working at the point of the service call. If I check WindowsIdentity.GetCurrent(), it's the user I expect.
If I inspect the WCF service proxy on the working and non-working servers, they look identical -- the part that deals with ClientCredentials is set to "" for Username and Password for both versions.
Any ideas on what else to check? Why would the NTLM data have DOMAIN and USER NAME set to NULL -- where does it pick that up from?
According to this:
http://support.microsoft.com/kb/207671
When IIS services an HTTP request, IIS performs impersonation so that access to resources to handle the request is limited appropriately. The impersonated security context is based on the kind of authentication performed for the request. The five different types of authentication available from IIS 4.0 are:
Authentication Type Impersonation Type
------------------------------------ ---------------------
Anonymous Access (no authentication) Network
Auto Password Synchronization is
ON (ON=default)
Anonymous Access (no authentication) IIS Clear Text
Auto Password Synchronization is OFF
Basic Authentication IIS Clear Text
NT Challenge/Response Authentication Network
Client SSL Certificate Mapping Interactive
In my case, I have a Network Token, but
Network tokens are "NOT" permitted to access network resources. (Network tokens are named so because this kind of token is traditionally created by a server when a user is authenticated across the network. To allow the server to use a network token to act as a network client and access another server is called "delegation" and is considered a possible security hole.)
The KB has many possible ways to avoid the problem

Restricted Remote WCF Service: Windows Authentication Prompt

I want to let remote administrators (with local or domain credentials) control my Windows service via a WCF TCP binding. To do this, I need to authenticate the remote user as an administrator. I can check the principal user/roles, but I don't know how to prompt the remote user for the correct user details/token.
This is related to my previous question on Restricting WCF TCP endpoint to Administrators. Instead of adding [PrincipalPermission(SecurityAction.Demand, Role = "Administrator")] to my restricted service method and catching a SecurityException, it seems I can check for it with:
if (!System.Threading.Thread.CurrentPrincipal.IsInRole("Administrators"))
return MethodResult.AccessDenied;
// haven't tested if it's the service thread or the remote user yet.
How do I prompt the remote user for Windows authentication if a Access Denied result was returned so I can reinitiate the connection as a different principal?
Of course, the change would need to be effected on the remote user's client application. Perhaps there is a cleaner WCF way to do it?
Edit: Searching for ".net impersonation" led me to this on CodeProject. Haven't had a chance to look, but this may be the way to go.
You need to pass in the user's credentials with your WCF call. Normally the client application just "captures" the currently running user's credentials. Alternatively you can specify a username and password explicitly. So you could prompt the user for an alternative set of credentials if you wish.
Either way, the client app needs to prompt the user. Your WCF call should return an error (code or exception) upon authorization failure and your client should capture that return and display a prompt to the user and retry with the new credentials. WCF by itself cannot handle prompting the user.
Here is an article on various means of passing credentials:
http://blogs.msdn.com/b/sonuarora/archive/2007/04/21/setting-client-credentials.aspx
Assuming this is hosted in IIS you need to turn off anonymouse authentication in the IIS Manager. This should force the user to login to the machine using a Windows account. You may also need to enable ASP.NET Impersonation.
Here is how you can prompt the user using the standard windows dialog using pInvoke How to show authentication dialog in C# .Net 3.5 SP1