How should one handle NSURLAuthenticationMethodXMobileMeAuthToken? - cocoa

We're using a NSURLSessionDataDelegate and have the following delegate method implemented:
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler { ... }
Frequently we find that users of iCloud receive a NSURLAuthenticationMethodXMobileMeAuthToken challenge. Sending back a rejection doesn't work (as the server won't try another challenge) and sending back an acceptance with
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
doesn't work either.
What are we supposed to do with this authentication challenge type? Has anyone else seen it?

For any protection space that you aren't explicitly handling, or for any credential type that you don't understand, you should typically use NSURLSessionAuthChallengePerformDefaultHandling (the credential is ignored, but typically pass nil) to tell the OS to handle the credential as though you didn't provide an authentication delegate method.

Related

MVC Prompt Query Parameter

I want to override Azure AD SSO login for a MVC web application. I don't want to log other applications out in the process, but require login for security purposes. I am using OAuth2.0 with OIDC via Owin for authentication.
I am trying to use the prompt=login query parameter, which should theoretically do the trick. I found a Github reference to this being recently made available in Core but cannot trace how to do it in MVC5.2
Is it possible to do it in the Application Builder? I tried adding .WithExtraQueryParameters ("prompt=login") to the ConfidentialClientApplicationBuilder when getting the access code. No luck.
Is there another workaround if the code doesn't come out-of-the-box?
EDIT: PublicClientApplication allows .WithPrompt(Prompt.Login) while ConfidentialClientApplication does not (also does not allow AcquireTokenInteractive) This is a web app so it needs the confidential builder. Tested using the Public builder and it logs in successfully. But I get an ActiveX instantiation error 'not in a single-threaded apartment'(?) Strange, unless that is how the token is being delivered perhaps. I also tested by changing to multitenant in Azure and by toggling Public client on and off.
Any ideas?
You could use ForceLogin to add paramter to ConfidentialClientApplicationBuilder.
ForceLogin: enables the application developer to have the user prompted for credentials by the service even if this would not be needed. This can be useful if Acquiring a token fails, to let the user re-sign-in. This is done by sending prompt=login to the identity provider. Again, we've seen it used in some security focused applications where the organization governance demands that the user re-logs-in each time they access specific parts of an application.
So, use the code as below:
result = await app.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.ForceLogin)
.ExecuteAsync();
The Modifier .WithExtraQueryParameters will not help you. You need to use .WithPrompt instead.Please refer article.
Example:
await PublicClientApplication
.AcquireTokenInteractive(scopes, null)
.WithAccount(CurrentUser)
.WithPrompt(Prompt.ForceLogin) // use login for your case
.ExecuteAsync();
I eventually resolved this as follows:
Under Notifications in the ConfigureAuth(IAppBuilder app) add a reference to a new task:
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
Then add the task:
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification
<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
// Forces the user to login.
if (notification.ProtocolMessage.Prompt == null)
{
notification.ProtocolMessage.Prompt = "login";
}
return Task.FromResult(0);
}
Hope that helps the next person with this issue.

Stop Auto Logon after failure - Custom Credential Provider Windows

I've taken up Widows Samples on Credential Providers and have built one using them as a reference. I'm able to log in seamlessly, wither by giving username and password manually. I've set
CustomCredential::SetSelected (__out BOOL* pbAutoLogon) {
*pbAutoLogon = TRUE; // FALSE;
return S_OK;
}
Now, AutoLogon, when the Tile is selected, is happening seamlessly.
As a test case, I changed the password, and as expected the Login fails. After failure, an error message appears and when I click OK ( this is the only option ), the credentials are resubmitted for a retry. How do can we stop this behavior? Which method gets called after the authentication failure?
I've handled ReportResult() but that did not help.
Thanks in advance.
It's been a while - but I believe GetSerialization() is called to return serialized credentials to LogonUI. You need to implement this as well. The credential provider samples I think have working code for KERB_INTERACTIVE_UNLOCK_LOGON.
You can also change *pbAutoLogon conditionally in SetSelected() - I do this in my credential provider depending on certain results.
ReportResult() would be called after GetSerialization returns its result to LogonUI. Inside ReportResult() you could do things like clear the password box (which is done in the samples code.)
If you're not returning serialized credentials in GetSerialization then I think you might get the kind of error you listed in your original post. In the credential samples KerbInteractiveUnlockLogonPack() is called in GetSerialization() and this is what 'logs' the user in effectively.
The error seems specific - 'the user has not been granted the requested logon type' so maybe it has something to do with the rights of the user you're testing with.
If you are using remote desktop, make sure your users are members of the right groups to be able to login (https://support.jumpdesktop.com/hc/en-us/articles/216424183-General-RDP-You-must-be-granted-the-Allow-log-on-through-the-Terminal-or-Remote-Desktop-Services-Right-) or if it is a regular user that it is allowed interactive login.
Also - SetSelected() Gets called when your credential provider is clicked on - I'm not sure if it gets called after every logon attempt or not (my guess is that it doesn't.) In my credential provider I am using a custom logon dialog that I show using SetSelected().

FB iOS SDK Custom Token Caching issue

I am trying to build an iOS application with a custom token caching mechanism. I authenticate to FB on the device and I store the FB access token on my server against a session token on my server and then make FB API requests from the server.
The FB Login works fine. I am able to cache the token onto my server. But the real problem happens when I run the app the next time after I logged into FB.
This is the flow I follow to check if my app is logged into FB.
1) Hit a url on my server to get the FBAccessToken for a given session token for my application. This is an asynchronous request.
2) The asynchronous request callback is fired. If a token is present, cache it in my custom FBSessionTokenCachingStrategy class.
3) In the callback I initialize a FBSession object using:
FBSession *session = [[FBSession alloc] initWithAppID:nil permissions:#[#"basic_info"] urlSchemeSuffix:nil tokenCacheStrategy:self.tokenCache];
Then, I check the session.state. If I get a FBSessionCreatedTokenLoaded, then I decide to proceed with the openBehaviour method. However, I get a FBSessionStateCreated instead of FBSessionStateCreatedTokenLoaded even when a token has been cached on the server and the fetchFBAccessTokenData returns a FBAccessTokenData object.
Wonder why this happens?
Here is my implementation of the fetchFBAccessTokenData method of my custom FBSessionTokenCachingStrategy class:
-(FBAccessTokenData*) fetchFBAccessTokenData {
NSLog(#"Fetching FB Access token");
if (self.fbTokenData != nil) {
NSLog(#"Found FB Token");
FBAccessTokenData *fbTokenData = [FBAccessTokenData createTokenFromString: [self.fbTokenData objectForKey:#"fb_token"] permissions:nil expirationDate:nil loginType:1 refreshDate:nil];
NSLog(#"%#",fbTokenData.accessToken);
return fbTokenData;
}
return nil;
}
It returns an FBAccessTokenData object but I still get an incorrect session state.
Does this happen because I am not returning the cached token correctly? I am implementing my code based on the standard example given for custom caching in the FB IOS SDK documentation.
It looks like your strategy is returning an FBAccessTokenData that has no permissions (which is not entirely unreasonable for your purposes unless you were to store permissions as well). When you init the session, however, specifying "basic_info" (while generally a good best practice, and required when asking for login that would prompt UI) will cause it to check that "basic_info" is included in the cached token. Since it is not, it will not load the cached token. For your purposes, you ought to be able to init the session with a nil permission array.

Can't get Twitter OAuth callback authentication to work in Cocoa application

I'm using MGTwitterEngine and OAuthConsumer frameworks. And mostly following the instructions at UsingOAuthConsumer.
In order to use OAuth and not have the user deal with the oob PIN based authentication, you need to enable a callback to the application. To do this on a desktop (or iOS) application, you need to set up a custom URI scheme that goes to an event handler in the app. I got this working, and tested it by using the custom URI in Safari. My app does open and the correct method is invoked. So far so good.
To do this for Twitter, you need to specify the callback URI in the settings for the application on Twitter's dev site. Here the problem starts. Twitter won't allow non-standard URIs. So "myapp://oauth/" is not allowed. It has to be an http or https URI. All the websites I referenced say to put a placeholder here, and override in the request token request. OK, so I put a dummy URL for my website here. Now to implement the override. Here's the code from one of the comments on how to so that:
OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:nil
realm:nil
signatureProvider:nil];
[request setOAuthParameterName:#"oauth_callback" withValue:#"callbackurl:"];
When I add that second method call, the request to twitter now fails. NSURLErrorDomain error -1012 or something similar (I forgot to write down the number).
I tried a number of ways, but was never able to override the callback URL. Does anyone have a sure-fire way of doing this? For now, I've changed the app to use the OOB PIN authentication method, but I'd sure like to remove that unnecessary step for the user.
Thanks!
joe
I finally gave up on the OAuthConsumer framework and switched to the Google GTMOAuth framework. That works fine.

How to integrate Twitter support into an iOS application?

How to integrate Twitter support into an iOS application?
Stefan Arentz's Twitter library is a pleasure to use - it contains the views you need, there is basically no coding to do. Do register your app early with twitter and get a submission to request xAuth authentication permission so that you do not have to use the clumsy web-based oAuth method. With xAuth it is as simple as submitting username and password and keeping the returned authentication token to submit a tweet.
Here is an example:
Call -(void)sendTweet from your IBAction.
// Sending tweets from within the application
-(void)sendTweet {
// check if device capable of sending tweets
if([TWTweetComposeViewControllercanSendTweet])
{
TWTweetComposeViewController *tweetSheet = [[TWTweetComposeViewControlleralloc] init];
[tweetSheet setInitialText:#"Twitting from my iSecret App"];
self.imageString = #"theSecret.png";
if(self.imageString) {
[tweetSheet addImage:[UIImageimageNamed:self.imageString]];
}
[selfpresentModalViewController:tweetSheet animated:YES];
}
else {
UIAlertView *alert = [[UIAlertViewalloc]initWithTitle:#"Sorry"message:#"You can't send a tweet right now, make sure your device has an internet connection and you have at least one Twitter account setup"delegate:selfcancelButtonTitle:#"Ok"otherButtonTitles:nil];
[alert show];
}
}

Resources