Microsoft.Xrm.Tooling.Connector.CrmServiceClient security token expires every 5 hrs, The user authentication failed error occurs - wcf

I am new to WCF, I have created the WCF service which connects and pulls the data from dynamic CRM. Everything works fine but after 5 hrs I am getting the below error, because of this error I see the exception The user authentication failed!. I understand security token gets expired and because of that I get the authentication error, after restarting the application pool everything seems to be good.
What would cause the security token expire? or how to reissue the token?
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Warning: 4 : Claims Connection reset tripped SecurityToken is Not Null Start From is Valid True End At is Valid False Microsoft.Xrm.Tooling.Connector.CrmServiceClient Warning: 4 : Re-Authenticating due to expired token # 05/20/2021 04:12:23
I am using AuthType=IFD in the connection string and below is my coding, I am passing the connection string from the web.config file. I am using RequireNewInstance=True; in the config file as I have a two crm servers to connect.
<add name="crmconnectionstring" connectionString="Url=https://urlhere; AuthType=IFD; RequireNewInstance=True;Domain=testdomain; Username=testusername; Password=; " />
public OrganizationServiceProxy service_;
CrmServiceClient CrmServiceClient_= new
CrmServiceClient(ConfigurationManager.ConnectionStrings["crmconnectionstring"].ConnectionString);
if (!CrmServiceClient_.IsReady)
{
if (CrmServiceClient_.LastCrmException != null)
throw CrmServiceClient_.LastCrmException;
throw new InvalidOperationException(CrmServiceClient_.LastCrmError);
}
service_ = CrmServiceClient_.OrganizationServiceProxy;
Update 1:
I have tried to renew the token but still it does not work. I am desperately looking for the support.
public OrganizationServiceProxy service;
service = CrmServiceClient_.OrganizationServiceProxy;
if (null != this.service.SecurityTokenResponse &&
DateTime.UtcNow.AddMinutes(15) >= this.service.SecurityTokenResponse.Response.Lifetime.Expires)
{
try
{
this.service.Authenticate();
}
catch (CommunicationException)
{
if (null == this.service.SecurityTokenResponse ||
DateTime.UtcNow >= this.service.SecurityTokenResponse.Response.Lifetime.Expires)
{
throw;
}
}
}

Related

Windows authentication fail with "401 Unauthorized"

I have a MVC client accessing a Web API protected by IDS4. They all run on my local machine and hosted by IIS. The app works fine when using local identity for authentication. But when I try to use Windows authentication, I keep getting "401 Unauthorized" error from the dev tool and the login box keeps coming back to the browser.
Here is the Windows Authentication IIS setting
and enabled providers
It's almost like that the user ID or password was wrong, but that's nearly impossible because that's the domain user ID and password I use for logging into the system all the time. Besides, according to my reading, Windows Authentication is supposed to be "automatic", which means I will be authenticated silently without a login box in the first place.
Update
I enabled the IIS request tracing and here is the result from the log:
As you can see from the trace log item #29, the authentication (with the user ID I typed in, "DOM\Jack.Backer") was successful. However, some authorization item (#48) failed after that. And here is the detail of the failed item:
What's interesting is that the ErrorCode says that the operation (whatever it is) completed successfully, but still I received a warning with a HttpStatus=401 and a HttpReason=Unauthorized. Apparently, this is what failed my Windows Authentication. But what is this authorization about and how do I fix it?
In case anyone interested - I finally figured this one out. It is because the code that I downloaded from IndentityServer4's quickstart site in late 2020 doesn't have some of the important pieces needed for Windows authentication. Here is what I had to add to the Challenge function of the ExternalController class
and here is the ProcessWindowsLoginAsync function
private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl)
{
var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
if (result?.Principal is WindowsPrincipal wp)
{
var props = new AuthenticationProperties()
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", AccountOptions.WindowsAuthenticationSchemeName },
}
};
var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));
if (AccountOptions.IncludeWindowsGroups)
{
var wi = wp.Identity as WindowsIdentity;
var groups = wi.Groups.Translate(typeof(NTAccount));
var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
id.AddClaims(roles);
}
await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props);
return Redirect(props.RedirectUri);
}
else
{
return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
}
}
Now my windows authentication works with no issues.

google oauth and refresh token confusion/questions

I had expected the refresh of an expired access token to happen during the authentication process instead of during an api access.
I think I understand why this happens - authorization is done once but an access token can expire at any time, therefore a refresh attempt needs to be attempted whenever the token is determined to be expired.
I'd like to confirm this is the right interpretation of what's going on.
My first clue was the part of the docs that said
If you use a Google API Client Library, the client object refreshes
the access token as needed as long as you configure that object for
offline access.
I am using the following:
google-oauth-client 1.24.1
google-oauth-client-java6 1.24.1
google-oauth-client-jetty 1.24.1
When I run with a completely invalid access token ("i am no good") and a valid refresh token and execute a
DCM API call to a com.google.api.client.googleapis.services.json.AbstractGoogleJsonClient subclass, I observe the following behavior:
control passes to com.google.api.client.auth.oauth2.Credential at method:
public final boolean refreshToken() throws IOException {
lock.lock();
try {
try {
TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
setFromTokenResponse(tokenResponse);
for (CredentialRefreshListener refreshListener : refreshListeners)
{
refreshListener.onTokenResponse(this, tokenResponse);
}
return true;
}
} catch (TokenResponseException e) {
boolean statusCode4xx = 400 <= e.getStatusCode() && e.getStatusCode() < 500;
// check if it is a normal error response
if (e.getDetails() != null && statusCode4xx) {
// We were unable to get a new access token (e.g. it may have been revoked), we must now
// indicate that our current token is invalid.
setAccessToken(null);
setExpiresInSeconds(null);
}
for (CredentialRefreshListener refreshListener : refreshListeners) {
refreshListener.onTokenErrorResponse(this, e.getDetails());
}
if (statusCode4xx) {
throw e;
}
}
return false;
} finally {
lock.unlock();
}
}
This goes out and gets a new access token as long as the refresh token is valid (i've tried using an invalid refresh token and watched it fail).
Upon successful retrieval of a new access token, control passes to
refreshListener.onTokenErrorResponse(this, e.getDetails());
The token is inserted into the proper objects and access continues.
If I run with a bad refresh token the above method fails with:
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad
Request
{
"error" : "invalid_grant",
"error_description" : "Bad Request"
}
Can anyone confirm I've got the right general idea?

CRM OrganizationServiceProxy authentication issue

We have an issue where our web app calls to CRM via Microsoft.Xrm.Sdk OriganizationServiceProxy are failing to authenticate. The issue appears to be environment specific i.e. the calls work on our DEV web server but fail when the app is promoted to our System Test environment. The code that fails is as follows:
using (var serviceProxy = this.serviceFactory.Impersonate(userProvider.PrincipalUserName).ServiceProxy)
{
var countResult = serviceProxy.RetrieveMultiple(new FetchExpression(query));
int? count = 0;
var entity = countResult.Entities.FirstOrDefault();
if (entity != null)
{
count = (int?)((AliasedValue)entity["activity_count"]).Value;
}
return count.Value;
}
The error that appears in our logs is:
System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
--- End of inner exception stack trace ---
I have double checked the apppool identity of the IIS site and CRM settings. Is there anything obvious here that we may have missed?
I found the connection to CRM Online was taking the longest time so I create one instance to pass round of the OrganizationServiceProxy with explicit credentials that I can easily switch between environments.
IServiceManagement<IOrganizationService> management = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(CrmUrl));
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = CrmUserName;
credentials.UserName.Password = CrmPassword;
AuthenticationCredentials authCredentials = management.Authenticate(new AuthenticationCredentials { ClientCredentials = credentials });
SecurityTokenResponse securityTokenResponse = authCredentials.SecurityTokenResponse;
OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(management, securityTokenResponse);
orgProxy.EnableProxyTypes();
_xrmService = new XrmServiceContext(orgProxy)

How to pass SMSESSION value from Win Client to asmx web service for Authentication

I am trying to implement the SSO authentication with our WPF application.
Following is scenario
We have our asmx web service hosted with our web application which is firewall protected.
To login our web application or to view our web service in browser from production server we need to login using sso id.
I have to implement the SSO authentication with our WPF application.
First I have to consume the 3rd party web service which return me valid SMSESSION in string format if user is authenticated.
Then I have to pass this SMSESSION to my web service which is behind the fire wall.
Now the problem which I am facing is that I am unable to pass the SMSESSION value to our web service for authentication.
When i Try this it throws an exception
The content type text/html; charset=iso-8859-1 of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '<HTML><HEAD><TITLE></TITLE></HEAD><BODY onLoad="document.AUTOSUBMIT.submit();">This page is used to hold your data while you are being authorized for your request.<BR><BR>You will be forwarded to continue the authorization process. If this does not happen automatically, please click the Continue button below.<FORM NAME="AUTOSUBMIT" METHOD="POST" ENCTYPE="application/x-www-form-urlencoded" ACTION="https://xxx.com/ssologinforms/SSO_Generic_RME.fcc?TYPE=33554432&REALMOID=06-49a328ee-0d11-103b-ad01-83323a2d304d&GUID=&SMAUTHREASON=0&METHOD=POST&SMAGENTNAME=-SM-ooM6KmTLLwbCHi%2ffOCEVUabjNhcgULT5joVqmn4M77Tf0PAu3BFcfbexTaiWfZ4N&TARGET=-SM-http%3a%2f%2fdev--srvspeq%2eog%2ege%2ecom%2fSRVSpeQWebService%2easmx"><INPUT TYPE="HIDDEN" NAME="SMPostPreserve" VALUE="+rB+TqoVGXah2Uij3lfKDdCf2jsgE2NAUoujo+dFiiJ7yzqgpQaVnxRangTzcB/faU6BOAAcSBFUMUA1RpOCnVRVjN1cFbL0KhVu3y6IySj4gJE6X797kXkzMNEZgozuEz96g6PgQ6e5+sjqZaaNGii+Cy26QaD16fqQTI5VGkLdnD0fhNvJjXXgSBLNZd77nZz0aaMmz4cGZwnAElk7POTF/NBKdxCXS1l0U/iqqozqfBz0aFqLMpsy'.
please help me out in doing this
I use following code to get the Valid SMSESSION
string userId = txtUsername.Text.Trim(); // User to be authenticate with site minder //xxxxxxxxx
string passwrod = txtPassward.Password.Trim(); //password of user to be authenticate with site minder //xxxxxxxx
string applicationID = "XXXXXX"; // Application id. To be authenticate with JBoss Server.//xxxxxxxx
string applicationPassword = "XXXXXXXXX";//applicationPassword to be authenticate with JBoss Sever.//xxxxxxxx
NamespaceName.AuthenticationServiceClient proxy = new NamespaceName.AuthenticationServiceClient();
AuthenticationServiceRequest request = new AuthenticationServiceRequest();
UserAttributes ut = new UserAttributes();
ut.userName = userId;
ut.password = passwrod;
request.userAttributes = ut;
AuthenticationServiceResponse response = null;
try
{
ServicePointManager.Expect100Continue = false;
proxy.ClientCredentials.UserName.UserName = applicationID;
proxy.ClientCredentials.UserName.Password = applicationPassword;
response = proxy.passwordAuthenticate(request);
if (response.result != null)
{
switch (response.result.ToString())
{
case "SUCCESS":
MessageBox.Show("Valid SMSESSION :" + response.smSession.ToString());
break;
case "ERROR":
MessageBox.Show("ERROR CODE :" + response.errCode.ToString() + "\n Error Message :" + response.errMsg.ToString());
break;
default: MessageBox.Show("Response is neither SUCCESS nor ERROR, its something different\nERROR CODE :" + response.errCode.ToString() + "\n " + response.errMsg.ToString());
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
How to pass SMSESSION to asmx web service

How to catch exception from UserNamePasswordValidator in WCF client application?

I've written simple WCF service using netTcpBinding and security mode="Message" and clientCredentialType="UserName". Everything works fine when I pass valid username and password, session is established the way I wanted.
However when the credentials are wrong exception is thrown though I can't catch it in my client application in try catch block.
Did anyone have the same problem ?
Here is my custom validator...
public class UserValidator : UserNamePasswordValidator
{
static int counter = 0;
public override void Validate(string userName, string password)
{
++counter;
Console.WriteLine(counter.ToString() + " " + DateTime.Now.ToShortTimeString());
if (userName != "test" || password != "test")
throw new FaultException("Bad username or password");
//throw new SecurityTokenException();
}
}
Why aren't you throwing the security token exception? That's what it's there for. At that point a message has not be sent and the channel has not be opened, so you can't get a fault back.
Do you have code that sets up the channel between the client and server? If so, is the channel failing to be created correctly - as with message security the client and server must perform the hadnshake, both providing their credentials to open a security channel. This must be established before any further communications will be enabled, and the fact that invalid credentials are passed will stop the channel being created I suspect.