I'm trying get RestKit (version 0.10.2) to authenticate with OAuth2. I'm using GTMOAuth2 to handle the OAuth interactions.
I've successfully gotten GTMOAuth2 to sign me in and make a request to the api I'm using.
I've also managed to get RestKit to make a request with my access token with this:
- (void)setRKAuthorizationToken:(NSString *)authorizationToken {
RKObjectManager* objectManager = [RKObjectManager sharedManager];
NSString* authHeader = [NSString stringWithFormat:#"Bearer %#", authorizationToken];
[objectManager.client setValue:authHeader forHTTPHeaderField:#"Authorization"];
}
In this code sample I am manually setting the HTTP header because RestKit's support for OAuth2 sets the header as Authorization: OAuth2 <accessToken> instead of Authorization: Bearer <accessToken>.
Anyway, this works great until the access token needs to be refreshed with the refresh token.
What I'd really like to do is tell RestKit to use GTMOAuth2Authentication's - (BOOL)authorizeRequest:(NSMutableURLRequest *)request; as it automatically fetches a new access token with the refresh token when the access token expires.
BTW, RestKit is phasing it's support for OAuth; authorizing requests with a third-party library is the suggested approach. I asked for an example and the response pointed me in the direction of classes to subclass, which are in the development branch.
So, the question is: Have you successfully integrated RestKit 0.10.x with GTMOAuth2 or know how to accomplish this?
I'm going to answer my own question here because I have something that works, but it's not ideal.
Basically I am continuing to sign requests manually, and to deal with the possibility of an expired token, I am using GTMOAuth to authorize a dummy request. The serious downside is that it means an extra request to the api. But, now I know I have a valid access token. Part of the trick is going to be knowing when to call loginWithBaseController:.
Here is the basic concept:
- (void)makeRequestToEnsureAccessTokenSuccess:(void (^)())block error:(void (^)(NSError*))errorBlock {
NSURL *url = [NSURL URLWithString:#"https://uri/to/a/basic/api/call.json"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// TODO: Only do this if we need to. It's kind of a waste to refresh the token
// all the time.
[self.gtmoauth authorizeRequest:request completionHandler:^(NSError *error) {
if (error) {
errorBlock(error);
} else {
[GTMOAuth2ViewControllerTouch saveParamsToKeychainForName:kKeychainItemName accessibility:NULL authentication:self.gtmoauth];
block();
}
}];
}
- (void)loginWithBaseController:(UIViewController *)baseViewController {
[self loadAuthFromKeyChain];
if (self.gtmoauth.canAuthorize) {
[self makeRequestToEnsureAccessTokenSuccess:^{
NSLog(#"setting RKAuthorizationToken with %#", self.gtmoauth.accessToken);
[self setRKAuthorizationToken: self.gtmoauth.accessToken];
[self.delegate authorizationFinished];
} error:^(NSError* error) {
[self logout];
[self showAuthorizationControllerFor:baseViewController];
}];
} else {
[self showAuthorizationControllerFor:baseViewController];
}
}
Anyway, I am still looking for a better solution. I thought I would post this in case it helps someone else at least through development.
This post on the RestKit Wiki, OAuth Support on Restkit references a complete solution using AFOAuth2Client.
The referenced sample iOS application at telegraphy-interactive/OAuthClientSetup has a pluggable architecture for authorized operations. It includes a class, OACSAuthOpRK that provides a RestKit RKObjectManager operation for making an authorized request.
The strategy used there is to wrap the request inside of the authorization. The authorization checks the currency of the OAuth2 authorization token. Finding the token current, it tries the request and checks the return status. Finding the token expired, or finding a 401 status return from the request, it will refresh the authorization token and try the request one more time.
Related
I am trying to use "Client-directed login operation" to authorize users with Facebook account on my azure-mobile service (http://msdn.microsoft.com/en-us/library/windowsazure/jj710106.aspx)
I downloaded and configured iOS Facebook SDK for the project;
Here is the code for user login:
NSArray* permissions = #[#"email, user_about_me, basic_info"];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession* session, FBSessionState status, NSError* error) {
if (!error) {
[_msClient loginWithProvider:provider
token:#{#"access_token" : [[session accessTokenData] accessToken]}
completion:^(MSUser* user, NSError* error) {
NSLog(#"%#", error);
}];
}
}];
This code returns error:
Error Domain=com.Microsoft.WindowsAzureMobileServices.ErrorDomain Code=-1302 "Error: The Facebook Graph API access token authorization request failed with HTTP status code 400" UserInfo=0x1768ba80 {NSLocalizedDescription=Error: The Facebook Graph API access token authorization request failed with HTTP status code 400}
I can confirm, that
NSString* access_token = [[session accessTokenData] accessToken];
returns a valid access token, because it works here https://developers.facebook.com/tools/explorer/?method=GET&path=me without any errors.
What am I doing wrong?
Had a similar problem and I can confirm that the error returned by Azure Mobile Service is most unhelpful. I eventually read up about what's happening under the hood here: https://developers.facebook.com/docs/facebook-login/access-tokens/#extending
Then I tried to acquire the long-lived token by invoking a GET request manually (https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id={app-id}&client_secret={app-secret}&fb_exchange_token={short-lived-token}) and here I finally got the real error message. In my case it turned out to be "The request is invalid because the app is configured as a desktop app" and simply flipping a switch in the Facebook app configuration fixed it.
In your case it might be a different error message, but I suggest you take this approach and see where it takes you.
This is old now but just had the same issue. Check that you don't have the "Is Your App Secret Embedded" switched on in. I had it on because I thought the ZUMO SDK would have it somewhere, but I guess it just lives on the cloud in your MS identity configuration.
i want to like a post in Facebook, i have post_id , and i am not able to find the FQL Query for liking particular post from the Facebook developer page in IOS SDK.
From Facebook developer page, it says that you can like a post with the used of HTTP POST method it means we can't use GraphAPI or fql.query to like a post.
Can anyone please share HTTP POST URL to like a post in Facebook.
is anyone here who develop the like button functionality for Facebook post using custom button in iOS.
Thanks in advance.
Here is an example if you are using Facebook SDK in iOS:
[FBRequestConnection startWithGraphPath:[NSString stringWithFormat:#"%#/likes", post_id]
parameters:[NSDictionary dictionary]
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
if (error)
{
NSLog(#"Error: %#", [error localizedDescription]);
}
else
{
NSLog(#"Result: %#", result);
}
}];
I see you are asking for fields(parameters) for HTTP POST URL. An HTTP POST request does not (usually) contain parameters on which you are probably used to when you pass them in a classic GET request such as ?param1=value¶m2=value after the script name in some URL.
POST request sends data to the server inside the message body, check out: http://en.wikipedia.org/wiki/POST_(HTTP)
Now that you know that, this is what you can do:
You CAN get the number of likes with a classic GET request, an URL that you can paste into any web browser and get the response, for example:
https://graph.facebook.com/260895413924000_605362559477282/likes?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This url will give you a response with all the people who liked that post/photo.
You can leave out the ?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx if you know the post/photo is public as this one is (https://www.facebook.com/photo.php?fbid=605362542810617&set=a.260905783922963.82517.260895413924000).
If it is not you need to generate one actual access_token(also for posting you NEED to generate one) and for testing you can do it here: https://developers.facebook.com/tools/explorer/
Now if you want to actually like the photo you can't simply form an URL that you can copy/paste inside your browser and which will trigger the like action. That's because browsers do not do POST requests, you need to do it trough code as Ivo Patrick Tudor Weiss suggested or eventually for testing purposes you can do it with curl utility from console like this:
curl --data "access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" https://graph.facebook.com/260895413924005362559477282/likes
and you can undo the like with HTTP DELETE ... like this:
curl --data "access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -X DELETE https://graph.facebook.com/260895413924000_605362559477282/likes
- UPDATE, for additional questions made by OP in the comments:
It is of course possible to use ASIHTTPRequest to make GET, POST and DELETE HTTP requests. However I would not advise the use of that library for your case. One reason is that the author of ASIHTTPRequest has stopped working on the library, and the other reason is that Facebook SDK for iOS is a better choice since with it you have many other things already taken care for you.
That being said here are the examples:
First type either one of these three combinations depending on what you want:
Get all people who liked the specific post:
(for simplicity I omitted the access_token here but you can append it to the URL if needed)
NSURL *url = [NSURL URLWithString:#"https://graph.facebook.com/260895413924000_605362559477282/likes"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
Like the specific post yourself:
NSURL *url = [NSURL URLWithString:#"https://graph.facebook.com/260895413924000_605362559477282/likes"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request appendPostData:[#"access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" dataUsingEncoding:NSUTF8StringEncoding]];
//[request setRequestMethod:#"POST"]; // <--- NOT NEEDED since it is the default if you previously called appendPostData
Unlike the post:
NSURL *url = [NSURL URLWithString:#"https://graph.facebook.com/260895413924000_605362559477282/likes"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request appendPostData:[#"access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" dataUsingEncoding:NSUTF8StringEncoding]];
[request buildPostBody];
[request setRequestMethod:#"DELETE"];
Then execute the actual request:
[request startSynchronous];
NSString *response = [request responseString];
NSLog(#"Response: %#", response);
Remember synchronous request is OK for testing but your GUI is going to be unresponsive if you use it on the main thread in an actual app. Learn how to do an asynchronous request here: http://allseeing-i.com/ASIHTTPRequest/How-to-use
As for your iOS example. It would be too much to write all the code here. And you already got the answer from Ivo Patrick Tudor Weiss which is perfectly correct. The only thing that is missing is the boilerplate code that you need to have to authenticate on Facebook and establish an FBSession.
I would advise you to go over this material here: https://developers.facebook.com/docs/getting-started/facebook-sdk-for-ios/
Download the latest SDK which contains also the sample code, and follow the tutorial on Facebook web. Then when you get the basics configured, get back to the answer you got from Ivo.
You can use Graph API to post a like to Facebook post. As it said in documentation here:
http://developers.facebook.com/docs/reference/api/post/
To create a like you need to issue a HTTP POST request to the POST_ID/likes connection with the publish_stream permission. You can suppress the notification created when liking a Post by passing a notify parameter with value of false.
I am trying to integrate an iOS application with Google App Engine using OAuth. I found that GTM has an OAuth Controller -- http://code.google.com/p/gtm-oauth/
Can it be used to connect to Google App Engine? If so, what do I put as the "scope" parameter in
- (id)initWithScope:(NSString *)scope
language:(NSString *)language
appServiceName:(NSString *)keychainAppServiceName
delegate:(id)delegate
finishedSelector:(SEL)finishedSelector;
I've tried to use my App Engine application's address (http://my-app-name.appspot.com) but it didn't work.
Thanks in advance!
btw this is sort of a follow up question to Authenticating into Google App Engine from an iOS device.
A late answer I know, but hopefully this will help someone:
MYSITE can be something like thunderofthor.com
Step 1:
Set up 2-legged OAuth for the App Engine domain of interest. To do this, log in as admin to https://www.google.com/a/MYSITE. Under advanced tools, click Manage OAuth domain key. Here, click 'Enable this consumer key' and 'Allow access to all APIs' to enable those options. On Google's side, you can now handle requests that use the MYSITE consumer key and the OAUTHCONSUMERSECRET.
Step 2:
In your servlet code, you can confirm the client has the correct credentials by requesting the OAuthConsumerKey which will be MYSITE
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String user = null;
try {
OAuthService oauth = OAuthServiceFactory.getOAuthService();
user = oauth.getOAuthConsumerKey();
LOG.info("Authenticated: " + user);
} catch (OAuthRequestException e) {
LOG.info("Not authenticated: " + e.getMessage());
}
Step 3:
Download the GTMOAuth package from Google. It will allow iOS to talk to your server effortlessly. You won't need the whole package for 2-legged auth. In fact, all you need is the GTMOAuthAuthentication files. To use in your code, do something like the following:
NSURL *url = [NSURL URLWithString:#"https://MYSITE/dosomething"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
GTMOAuthAuthentication *auth = [[GTMOAuthAuthentication alloc] initWithSignatureMethod:kGTMOAuthSignatureMethodHMAC_SHA1 consumerKey:#"MYSITE" privateKey:#"OAUTHCONSUMERSECRET"] ;
[auth setVersion:#"1.0"];
[auth addRequestTokenHeaderToRequest:request];
// Perform request and get JSON back as a NSData object
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
There! Effortless secure communication without requiring usernames and passwords!
I'm using the Facebook SDK for iOS in my app: http://github.com/facebook/facebook-ios-sdk
The oAuth token expires after about 2 hours. How can I "refresh" the oAuth token without having to call the [Facebook authorize...] method again - which shows an empty Facebook dialog briefly if the user had previously logged in? What I want to avoid is requiring the user to re-login to FB each time they use the app - say, day to day.
I am already saving / restoring oAuth tokens when the app exits / starts. And I can check to see if the token is valid using [Facebook isSessionValid], or by checking the expire time on the token. But what to do if the token has expired? I've read that it is possible to "refresh" the token, but I don't understand how this is done.
I don't want to request "offline_access" permission, which would give me a "forever" token.
Help!?
Facebook's implementation of OAuth doesn't support token refresh.
You have 2 types of access_tokens in Facebook. Short term token, which is given by default and a long term token which is given if you request offline_access. If refresh token were supported, it was the same as giving a offline_access token for all apps.
As long as the user has an active facebook session on your web control, you can request a new access_token just by accessing https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token or probably some iOS SDK command that does the same (never worked with it so I can't tell). This kind of request will not ask the user to login again, but will use the previous session that was created during the first login.
Since none of these answers actually addressed the question I am going to detail how I have implemented OAuth token refresh using The Facebook SDK.
The SDK will automatically refresh your tokens when you make requests however, in my scenario we send the tokens to our servers and we need to use the latest token. So when our server indicates that we need new tokens this is what we do:
Note You can either pass the AppID into the FBSession or you can add the FacebookAppID key to your App's plist (this is what we do).
- (void)renewFacebookCredentials {
if (FBSession.activeSession.state == FBSessionStateOpen ||
FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
[self sessionStateChanged:[FBSession activeSession] state:[FBSession activeSession].state error:nil];
} else {
// Open a session showing the user the login UI
// You must ALWAYS ask for public_profile permissions when opening a session
[FBSession openActiveSessionWithReadPermissions:#[#"public_profile",#"email"]
allowLoginUI:NO
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
//this block will run throughout the lifetime of the app.
[self sessionStateChanged:session state:state error:error];
}];
}
}
The you can use the sessionStateChanged: method that Facebook include in their documentation but a simplified handler looks like this:
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error {
// If the session was opened successfully
NSString *accessToken;
if (!error && state == FBSessionStateOpen && [[session accessTokenData] accessToken]){
// Show the user the logged-in UI
//#see http://stackoverflow.com/questions/20623728/getting-username-and-profile-picture-from-facebook-ios-7
accessToken = [[session accessTokenData] accessToken];
//Now we have an access token, can send this to the server...
} else {
//No access token, show a dialog or something
}
//either call a delegate or a completion handler here with the accessToken
}
Be aware that some of the FBSession API calls check for thread affinity so I found that I had to wrap all my FBSession calls inside a dispatch_async(dispatch_get_main_queue(), ^{...
Just do [ [FBSession session] resume] if it return false do login again
Facebook iOS SDK doesn’t handle the session storage.
FBSessionDelegate is a callback interface that your application should implement. it's methods will be invoked on application's successful login or logout.
See the example application facebook-ios-sdk/sample/DemoApp/Classes/DemoAppViewController.m for fbDidLogin, fbDidNotLogin and fbDidLogout methods
As per the Facebook SDK documentation:
The Facebook SDK automatically refreshes the user's session if
necessary. When it does this, the state also transitions to the
FBSessionStateOpenTokenExtended state.
Also to further clarify (since SDK version 3.1):
The SDK refreshes session automatically on API calls.
It also refreshes the token data as needed when follow-on authentication or Facebook API calls made using the SDK.
As of today Facebook is supposed to refresh tokens automatically, requests to GraphAPI can be done without providing token string either (Facebook handles it under the hood).
Moreover, if it happens that user wasn't using app for a long time and his token managed to expire, on your next request to Graph API an alert will be shown by Facebook's SDK asking user to relogin (all that is handled by Facebook and when done - will return into FBSDKGraphRequest's closure).
However, if someone really has a reason to manually refresh access token, here's an example (Swift 4):
private var selfDestructableNotificationToken: NotificationTokenThatAutomaticallyRemovesObserver?
final class NotificationTokenThatAutomaticallyRemovesObserver: NSObject { // more info here: https://oleb.net/blog/2018/01/notificationcenter-removeobserver/
let token: Any
init(_ token: Any) { self.token = token }
deinit { NotificationCenter.default.removeObserver(token) }
}
...
if let currentFBToken = FBSDKAccessToken.current() { // if this is a Facebook user, not an email-based user
if FBSDKAccessToken.currentAccessTokenIsActive() { // and his token has not expired yet
let token = NotificationCenter.default.addObserver(forName: NSNotification.Name.FBSDKAccessTokenDidChange, object: nil, queue: OperationQueue.main) { notification in
if let userInfo = notification.userInfo, let refreshedToken = userInfo["FBSDKAccessToken"] as? FBSDKAccessToken {
self.fbAccessToken = refreshedToken.tokenString
} else {
self.fbAccessToken = currentFBToken.tokenString // falling back to using an old token (better than none)
}
}
self.selfDestructableNotificationToken = NotificationTokenThatAutomaticallyRemovesObserver(token)
FBSDKAccessToken.refreshCurrentAccessToken { _, _, error in
if let error = error {
print("failed to refresh Facebook token with error \(error.localizedDescription)")
self.fbAccessToken = currentFBToken.tokenString // falling back to an old token (better than none)
}
}
} else if FBSDKAccessToken.current().isExpired { // unlucky user. Probably returned to the app after > 2 months break
self.fbAccessToken = currentFBToken.tokenString // assigning expired token. Facebook will ask user to relogin as soon as we call Graph API with that expired token
}
}
I have a cocoa class set up that I want to use to connect to a RESTful web service I'm building. I have decided to use HTTP Basic Authentication on my PHP backend like so…
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
//Stuff that users will see if they click 'Cancel'
exit;
}
else {
//Validation Code
echo "You entered info.";
}
?>
At this point I'm using a synchronous NSURLConnection, which I understand the Apple documentation states has less support for Authentication.
But is it even possible at all? I can do cookie authentication very easily sans NSURLProtectionSpaces or NSURLCredentials or any of the authentication classes. Also, are there any resources where I can read more about the Cocoa Authentication classes?
Thanks.
UPDATE: mikeabdullahuk
The code you supplied (the second example) is almost identical to what I had written. I have done some more investigating, and discovered that the NSURLConnection is returning an error…
Error Domain=NSURLErrorDomain Code=-1012 UserInfo=0x1a5170 "Operation could not be completed. (NSURLErrorDomain error -1012.)"
The code corresponds to NSURLErrorUserCancelledAuthentication. So apparently my code is not accessing the NSURLCredentialStorage and instead is canceling the authentication. Could this have anything to do with the PHP HTTP Authentication functions? I'm quite confused at this point.
A synchronous NSURLConnection will absolutely work with NSURLCredentialStorage. Here's how things usually work:
NSURLConnection requests the page from the server
The server replies with a 401 response
NSURLConnection looks to see what credentials it can glean from the URL
If the URL did not provide full credentials (username and password), NSURLConnection will also consult NSURLCredentialStorage to fill in the gaps
If full credentials have still not been determined, NSURLConnection will send the -connection:didReceiveAuthenticationChallenge: delegate method asking for credentials
If the NSURLConnection now finally has full credentials, it retries the original request including authorization data.
By using the synchronous connection method, you only lose out on step 5, the ability to provide custom authentication. So, you can either pre-provide authentication credentials in the URL, or place them in NSURLCredentialStorage before sending the request. e.g.
NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://user:pass#example.com"]];
[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
or:
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"user"
password:#"pass"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"example.com"
port:0
protocol:#"http"
realm:nil
authenticationMethod:nil];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
[protectionSpace release];
NSURLRequest *request =
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://example.com"]];
[NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
In a situation where a 401 or other authentication challenge is unacceptable/impossible, I sometimes use a dummy CFHTTPMessage to generate the authetication line, then copy that back into the NSURLRequest:
// assume NSString *username and *password exist and NSURLRequest *urlRequest
// exists and is fully configured except for HTTP Basic Authentication..
CFHTTPMessageRef dummyRequest =
CFHTTPMessageCreateRequest(
kCFAllocatorDefault,
CFSTR("GET"),
(CFURLRef)[urlRequest URL],
kCFHTTPVersion1_1);
CFHTTPMessageAddAuthentication(
dummyRequest,
nil,
(CFStringRef)username,
(CFStringRef)password,
kCFHTTPAuthenticationSchemeBasic,
FALSE);
authorizationString =
(NSString *)CFHTTPMessageCopyHeaderFieldValue(
dummyRequest,
CFSTR("Authorization"));
CFRelease(dummyRequest);
[urlRequest setValue:authorizationString forHTTPHeaderField:#"Authorization"];
This may seem completely a bizarre way to do it but it is tolerant of situations where the username/password aren't URL clean and where NSURLRequest refuses to consult the NSURLCredentialStorage because the server isn't actually sending a HTTP 401 (for example it sends a regular page instead).
I would note mikeabdullahuk's answer is good but also if you use NSURLCredentialPersistencePermanent instead of per session it will store the credentials in the users keychain so next time you can check NSURLCredentialStorage for a non nil value for the default credentials for a protection space and if you get a non nil value you can just pass the credentials in. I am using this method right now for a delicious.com client I am writing and it works very well in my tests.
Set your credential as the default credential for the protectionspace:
// Permananent, session, whatever.
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence: NSURLCredentialPersistencePermanent];
// Make sure that if the server you are accessing presents a realm, you set it here.
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:#"blah.com" port:0 protocol:#"http" realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
// Store it
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
At this point, any subsequent NSURLConnection that is challenged using a protection space that matches what you set will use this credential