ADAL - AcquireTokenHandlerBase.cs: System.ArgumentNullException: String reference not set to an instance of a String - xamarin

I used ADAL with ADFS for authenticating web api calls within Xamarin and is experiencing an issue when repeating the authentication process, it appears to be having issue with getting token from the in-memory cache.
Interestingly, I have another demo app which does the same thing and doesn't have the same issue...
The code used is as below, if anyone can shield some lights on how to debug it further it will be much appreciated.
try
{
AuthenticationContext ac = new AuthenticationContext(authority, false);
try
{
ar = ac.AcquireTokenSilentAsync(resourceURI, clientID).Result;
}
catch (AggregateException exc)
{
//do nothing?
}
if (ar == null)
{
ar = await ac.AcquireTokenAsync(resourceURI, clientID, new Uri(clientReturnURI), parent);
}
**catch (Exception ex)** //always been hit
{
2016-08-14 22:54:46.075 TimeSheetiOS[70494:1224472] 8/15/2016 5:54:46
AM: c7b85581-cef2-492c-86ee-5686a5d4de67 - TokenCache.cs: Looking up
cache for a token... 2016-08-14 22:54:46.076
TimeSheetiOS[70494:1224472] 8/15/2016 5:54:46 AM:
c7b85581-cef2-492c-86ee-5686a5d4de67 - TokenCache.cs: An item matching
the requested resource was found in the cache 2016-08-14 22:54:46.076
TimeSheetiOS[70494:1224472] 8/15/2016 5:54:46 AM:
c7b85581-cef2-492c-86ee-5686a5d4de67 - TokenCache.cs: 29.0067555833333
minutes left until token in cache expires 2016-08-14 22:54:46.077
TimeSheetiOS[70494:1224472] 8/15/2016 5:54:46 AM:
c7b85581-cef2-492c-86ee-5686a5d4de67 - TokenCache.cs: A matching item
(access token or refresh token or both) was found in the cache
2016-08-14 22:54:46.082 TimeSheetiOS[70494:1224472] 8/15/2016 5:54:46
AM: c7b85581-cef2-492c-86ee-5686a5d4de67 - AcquireTokenHandlerBase.cs:
System.ArgumentNullException: String reference not set to an instance
of a String. Parameter name: s at System.Text.Encoding.GetBytes
(System.String s) [0x00006] in
/Users/builder/data/lanes/3539/f37444ae/source/maccore/_build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/external/referencesource/mscorlib/system/text/encoding.cs:1083
at
Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.CreateSha256Hash
(System.String input) [0x0000c] in :0 at
Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.LogReturnedToken
(Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult
result) [0x00067] in :0 at
Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.PostRunAsync
(Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult
result) [0x

Related

Why does OIDC login breaks in Edge but not in FireFox?

I am wokring on a website (.NET Framework 4.6.1) and we implemented OIDC authentication (IdentityServer4). The implementation is very basic, nothing fancy just some code challange and token validation. We tested it and it worked real nice on both Edge and FireFox.
Then we were asked to implement "acr_values" parameter for MFA. In the authentication configuration, specifically inside RedirectToIdentityProvider (which is part of Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationNotifications), we add the specified "acr_values" parameter the following way (the value itself is set in a config file, and its similar to "xyz:asd:wtf:qwe"):
n.ProtocolMessage.AcrValues = authCfg.AcrValues
In a very similar setup (by similar i mean almost identical) it is working without any issues. For my setup it only works in Firefox. When trying in Edge we get AuthenticationFailed (which is also a Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationNotifications) with the following error:
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup
OIDC-Notification: AuthenticationFailed:
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup Value cannot
be null. Parameter name: s
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup
-TargetSite-------------------------------
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup Byte[]
FromBase64String(System.String)
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup
-Source-----------------------------------
2021-05-26 13:00:08.0633 ERROR MT.Translate.Startup mscorlib
In development enviroment the behaviour is a bit different. We do not get AuthenticationFailed, because after verifying the login information IdentityServer's redirection does nothing, but return us to the same login screen.
To summerize, without "acr:values" MFA was not working, but otherwise it was working in both Edge and Firefox. After implementig "acr_values" Firefox was working with MFA but not in Edge. So we rolled back to the previous version, where we have no "acr_values" and now MFA works with Edge and Firefox too.
The error does not make any sense to me. There is no parameter called "s", at least I have never heard of it in the context of authentication. The fact that without the necessary code it works does not make any sense to me. Also how can it work on Firefox and not on Edge?
Bonus Objective: Only in Edge a png is not appearing. It was not touched and in every other browser it shows up. How and why is my question.
Thank you for reading my post and I am looking forward to any insight what is happening.
Some code snippets:
oicdAuthOpt.Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication && AppSettingsKey.AuthCodeChallangeEnabled.Enabled)
{
// generate code verifier and code challenge
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64UrlEncoder.Encode(challengeBytes);
}
// set code_challenge parameter on authorization request
n.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
n.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
if (AppSettingsKey.MultiFactorAuthEnabled.Enabled)
n.ProtocolMessage.AcrValues = authCfg.AcrValues ?? n.ProtocolMessage.AcrValues;
// remember code verifier in cookie (adapted from OWIN nonce cookie)
// see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L85
RememberCodeVerifier(n, codeVerifier);
}
logger.Debug("OIDC-Notification: RedirectToIdentityProvider Called");
//if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
logger.Debug(" RequestType=" + OpenIdConnectRequestType.Logout);
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
logger.Debug(" IdTokenHint got from n.OwinContext.Authentication.User");
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
}
logger.Debug(" IdTokenHint=" + n?.ProtocolMessage?.IdTokenHint);
}
return Task.CompletedTask;
},
Code for the IndentityServer is on their github (Quickstart).
For authorization middleware we made a custom System.Web.Mvc.AuthorizeAttribute.
public override void OnAuthorization(AuthorizationContext filterContext)
{
try
{
if (AppSettingsKey.LoginEnabled.Enabled && AppSettingsKey.OpenIdConnectSSOEnabled.Enabled)
{
var cookie = HttpContext.Current.Request.Cookies["oidc.default"];
if (cookie == null)
{
logger.Debug("oidc.default is null -> HandleUnauthorizedRequest");
base.HandleUnauthorizedRequest(filterContext);
}
else
{
if (CookieKeyStore.Instance.CheckIfContains(cookie.Value))
{
if (!CookieKeyStore.Instance.isExpired(cookie.Value))
{
logger.Debug("oidc.default is not expired:" + cookie.Value + " -> OnAuthorization");
//requires oidc.default and ASP.NET_SessionID cookies
base.OnAuthorization(filterContext);
}
else
{
logger.Debug("oidc.default is expired:" + cookie.Value + " -> HandleUnauthorizedRequest");
base.HandleUnauthorizedRequest(filterContext);
}
}
else
{
logger.Debug("insert oidc.default into the KeyStore:" + cookie.Value + " -> OnAuthorization");
CookieKeyStore.Instance.HandleCookies(cookie);
base.OnAuthorization(filterContext);
}
}
}
else
base.OnAuthorization(filterContext);
}
catch (Exception e)
{
logger.Error(e, "Exception while overriding the OnAuthorization method.");
}
}
"oidc.default" is our custom cookie configured into OIDC.
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieName = "oidc.default",
CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager(),
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnResponseSignOut = context =>
{
CookieKeyStore.Instance.Clear(context.Request.Cookies["oidc.default"]);
}
}
});

Why does my findOne query hang indefinitely?

I just created a new project [GitHub] with yarn create strapi-app to test model lifecycle methods. I'm making a write-once read-many field called number_of_onsite_lessons.
I want to have a field where a user can specify how many Onsine Lessons should be generated when creating an Onsite Course and then disable that field - or at least throw an error when they try to change its value.
To this end, I wrote a lifecycle method of OnsiteCourse:
// Before updating a value.
// Fired before an `update` query.
beforeUpdate: async (model, attrs, options) => {
const prev = await strapi.query("onsite-course").findOne({_id: model.id});
console.log(prev,model);
if (prev.number_of_onsite_lessons != model.number_of_onsite_lessons) {
throw new Error("Can't change number of lessons - delete or create onsite lessons instead.")
}
if (prev.number_of_onsite_projects != model.number_of_onsite_projects) {
throw new Error("Can't change number of projects - delete or create onsite projects instead.")
}
},
When I update an OnsiteCourse entity, the code runs, but it stops at await strapi.query("onsite-course").findOne({...}) and then hangs indefinitely. I don't get an error, nor do I get that console.log on the next line.
After a while, this error shows up in the console:
[2020-03-17T07:42:30.558Z] error TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
at Bluebird.try.then.catch (/home/teri/projects/strapi/new/node_modules/knex/lib/client.js:318:17)
at tryCatcher (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/util.js:16:23)
at /home/teri/projects/strapi/new/node_modules/bluebird/js/release/catch_filter.js:17:41
at tryCatcher (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/promise.js:725:18)
at _drainQueueStep (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/teri/projects/strapi/new/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:443:21)
I got the same issues using sqlite connector (with 3.0.0-beta.20)
// tryed on beforeCreate, beforeUpdate and beforeSave
await strapi.query("product").findOne({ id: 1 })
await strapi.api.product.services.product.findOne({ id: 1 })
await strapi.api.product.controllers.product.findOne({ params: { id: 1 } })
await strapi.services.product.findOne({ id: 1 })
solved by using mongodb (mysql and others should work too !)

Google.Apis.Email_Migration_v2

I am attempting to retrieve the HttpStatusCode from every UploadAsync method call. I need the status code as to properly perform an exponential back-off algorithm to retry a failed upload, display an error message to the user when not retrying the upload and to report success of the upload. I do not care how it is received, so long as it is clean and not being parsed from the Exception.Message (string) property like Tor Jonsson suggested in the link provided below.
To force the "Bad Request Error [400]" I simply provided an invalid userkey (email) in the constructor for MailResource.InsertMediaUpload.
e.g. MailResource.InsertMediaUpload(mailItem, "invalidEmail#domain.com", stream, "message/rfc822")
Problem
1) GoogleApiException.HttpStatusCode is always 0 (unavailable). Even when Exception.Message appears to contain a status code in brackets. e.g. [400]
2) Cannot find GoogleApiRequestException.
Questions
1) What is the best way to perform the exponential back-off algorithm???
2) Is this the expected behaviour for this property in this case?
3) Does GoogleApiRequestException still exist, if so where?
Side Note:
I also noticed that the GoogleApiRequestException class is no longer in the same file as GoogleApiException class. Has it been moved to another namespace or deleted? Because I would like to attempt to catch a GoogleApiRequestException object and grab its RequestError object.
I added links to the two diffs for what I mean:
Before: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=a8e27790f8769c1d6aaae030bb46c79daa7cdbad
After: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=d6f06e92d90b635c179013e2c287b42b82909c09
Sources
I'm using the latest binaries from NuGet (1.6.0.8-beta)
The only question I found related to my problem: (Can only post two links... heres the raw)
stackoverflow.com/questions/18985306/httpstatuscode-not-set-in-exceptions-when-using-google-net-apis
Code: (Using a custom logger to write to debugview)
public int Index; // Used to Id the process
private void TryUpload(MailResource.InsertMediaUpload upload, out IUploadProgress uploadProgress, out bool retryUpload)
{
uploadProgress = null;
retryUpload = false;
CancellationToken token;
try
{
uploadProgress = upload.UploadAsync(token).Result;
if (uploadProgress.Exception != null)
{
_logger.WriteTrace("EXCEPTION!!! Type: {0}", uploadProgress.Exception.GetType().ToString()); // Remove:
// *) Handle all of the various exceptions
if (uploadProgress.Exception is JsonReaderException)
{
JsonReaderException jreEx = uploadProgress.Exception as JsonReaderException;
_logger.WriteTrace("JsonReaderException-> Message: {0}", jreEx.Message);
}
if (uploadProgress.Exception is TokenResponseException)
{
TokenErrorResponse trEx = uploadProgress as TokenErrorResponse;
_logger.WriteTrace("TokenErrorResponse-> Message: {0}", trEx.Error);
}
if (uploadProgress.Exception is HttpRequestValidationException)
{
HttpRequestValidationException hrvEx = uploadProgress.Exception as HttpRequestValidationException;
_logger.WriteTrace("HttpRequestValidationException-> Message: {0}", hrvEx.Message);
_logger.WriteTrace("HttpRequestValidationException-> Status Code: {0}", hrvEx.GetHttpCode());
}
if (uploadProgress.Exception is GoogleApiException)
{
GoogleApiException gApiEx = uploadProgress.Exception as GoogleApiException;
_logger.WriteTrace("GoogleApiException-> Message: {0}", gApiEx.Message);
_logger.WriteTrace("GoogleApiException-> Status Code: {0}", gApiEx.HttpStatusCode);
}
}
}
catch (Exception ex)
{
_logger.WriteTrace(ex, "An exception occured while uploading...");
}
finally
{
if (uploadProgress != null)
_logger.WriteTrace("Upload Completed... Status: {0} Exception?: {1}",
uploadProgress.Status,
(uploadProgress.Exception == null) ? "None" : uploadProgress.Exception.ToString());
else
_logger.WriteTrace("Upload Aborted... Exited without returning a status!");
}
}
Output Snippet
[5224] (T101) VSLLC: EXCEPTION!!! Type: Google.GoogleApiException
[5224] (T101) VSLLC: GoogleApiException-> Message: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224] (T101) VSLLC: GoogleApiException-> Status Code: 0
[5224] (T101) VSLLC: Upload Completed... Status: Failed Exception?: The service admin has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224]
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
[5224] at Google.Apis.Upload.ResumableUpload`1.d__0.MoveNext() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis\Apis[Media]\Upload\ResumableUpload.cs:line 373
Sorry for the extensive post! Thanks for your time!
The library already supports exponential back-off for 503 responses. In case of 400 (bad request) you should not retry, because you will get the same response over and over again.
Take a look in the service initializer parameter DefaultExponentialBackOffPolicy
You can also take a look in our ExponentialBackOff implementation. BackOffHandler wraps the logic and implements unsuccessful response handler and exception handler.
GoogleApiRequest doesn't exists anymore.
It looks like we are not setting the status code properly, as you can find here. I open a new issue in our issue tracker, available here - https://code.google.com/p/google-api-dotnet-client/issues/detail?id=425. Feel free to add more content to it.

How do I configure ServiceStack.net to authenticate using the OAuthProvider against Google

I'd like to configure ServiceStack.net to authenticate using the OAuthProvider against Google. Here is my current configuration:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new OAuthProvider(appSettings,
"https://accounts.google.com/o/oauth2/auth",
"google",
"Google Client ID",
"Google Client secret")
}));
However, I get the following error:
response Status
error Code ArgumentNullException
message String reference not set to an instance of a String. Parameter name: s
stack Trace
[Auth: 8/19/2013 7:48:47 PM]: [REQUEST: {provider:google}] System.ArgumentNullException: String reference not set to an instance of a String. Parameter name: s at System.Text.Encoding.GetBytes(String s) at ServiceStack.ServiceInterface.Auth.OAuthUtils.PercentEncode(String s) at ServiceStack.ServiceInterface.Auth.OAuthAuthorizer.<>c__DisplayClass3.<MakeSignature>b__1(String k) at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at System.Linq.Buffer`1..ctor(IEnumerable`1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) at ServiceStack.ServiceInterface.Auth.OAuthAuthorizer.MakeSignature(String method, String base_uri, Dictionary`2 headers) at ServiceStack.ServiceInterface.Auth.OAuthAuthorizer.AcquireRequestToken() at ServiceStack.ServiceInterface.Auth.OAuthProvider.Authenticate(IServiceBase authService, IAuthSession session, Auth request) at ServiceStack.ServiceInterface.Auth.AuthService.Authenticate(Auth request, String provider, IAuthSession session, IAuthProvider oAuthConfig) at ServiceStack.ServiceInterface.Auth.AuthService.Post(Auth request) at lambda_method(Closure , Object , Object ) at ServiceStack.ServiceHost.ServiceRunner`1.Execute(IRequestContext requestContext, Object instance, TRequest request)
According to the network trace, nothing ever hits Google.
Thanks!
I also had this problem. My solution was to double check the Web.Config in the root of the service. I didn't have the ServiceStack OAuth Config setup correctly there.
Use the keys:
<add key="oauth.GoogleOpenId.RedirectUrl" value="http://bootstrapapi.apphb.com/friends"/>
<add key="oauth.GoogleOpenId.CallbackUrl" value="http://bootstrapapi.apphb.com/api/auth/GoogleOpenId"/>
and the Google IAuthProvider
new GoogleOpenIdOAuthProvider(appSettings), //Sign-in with Google OpenId

How to validate credentials in EWS Java API

I am using EWSJavaAPI 1.1.5. I am trying to login with invalid credentials, but I don't get any exceptions.
Please advise how to detect and handle invalid login.
Here is my code:
String host = "myhost";
ExchangeService service = null;
try {
service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials("wrongemail",
"wrongpass");
service.setCredentials(credentials);
service.setUrl(new java.net.URI("https://" + host
+ "/EWS/Exchange.asmx"));
} catch (Exception e) {
e.printStackTrace();
}
Found it, i had to bind the service to a folder:
Folder.bind(service, WellKnownFolderName.Inbox);
and if the credentials are wrong, HttpErrorException is thrown.

Resources