How to Do Authentication in Uiwebview Properly

How to do authentication in UIWebView properly?

Try to use sharedCredentialStorage for all domains you need to authenticate.

Here is working sample for UIWebView it was tested against Windows IIS having only BasicAuthentication enabled

This is how to add your site credentials:

NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];

[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
[protectionSpace release];

Edit: same code in Swift 4

let login = "MYDOMAIN\\myname"
let credential = URLCredential(user:login, password:"mypassword", persistence:.forSession)
let protectionSpace = URLProtectionSpace(host:"myhost", port:80, protocol:"http", realm:"myhost", authenticationMethod:NSURLAuthenticationMethodDefault)
URLCredentialStorage.shared.setDefaultCredential(credential, for:protectionSpace)

Your webView is supposed to work now, if it does not work use next code to debug, especially check log messages of didReceiveAuthenticationChallenge.

    #import "TheSplitAppDelegate.h"
#import "RootViewController.h"

@implementation TheSplitAppDelegate

@synthesize window = _window;
@synthesize splitViewController = _splitViewController;
@synthesize rootViewController = _rootViewController;
@synthesize detailViewController = _detailViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the split view controller's view to the window and display.
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];

NSLog(@"CONNECTION: Add credentials");

NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];

[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
[protectionSpace release];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://myhost/index.html"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:12
];

NSLog(@"CONNECTION: Run request");
[[NSURLConnection alloc] initWithRequest:request delegate:self];

return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{

}

- (void)applicationDidEnterBackground:(UIApplication *)application
{

}

- (void)applicationWillEnterForeground:(UIApplication *)application
{

}

- (void)applicationDidBecomeActive:(UIApplication *)application
{

}

- (void)applicationWillTerminate:(UIApplication *)application
{

}

- (void)dealloc
{
[_window release];
[_splitViewController release];
[_rootViewController release];
[_detailViewController release];
[super dealloc];
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"CONNECTION: got auth challange");
NSString* message = [NSString stringWithFormat:@"CONNECTION: cred cout = %i", [[[NSURLCredentialStorage sharedCredentialStorage] allCredentials] count]];
NSLog(message);
NSLog([connection description]);

NSLog([NSString stringWithFormat:@"CONNECTION: host = %@", [[challenge protectionSpace] host]]);
NSLog([NSString stringWithFormat:@"CONNECTION: port = %i", [[challenge protectionSpace] port]]);
NSLog([NSString stringWithFormat:@"CONNECTION: protocol = %@", [[challenge protectionSpace] protocol]]);
NSLog([NSString stringWithFormat:@"CONNECTION: realm = %@", [[challenge protectionSpace] realm]]);
NSLog([NSString stringWithFormat:@"CONNECTION: authenticationMethod = %@", [[challenge protectionSpace] authenticationMethod]]);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// release the connection, and the data object
[connection release];

// inform the user
NSLog(@"CONNECTION: failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"CONNECTION: received response via nsurlconnection");
}

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
{
NSLog(@"CONNECTION: USE!");
return YES;
}

@end

The final solution for WebView authentication was based on custom protocol implementation. All protocols registered as a stack, so if you redefine HTTP protocol it would intercept all requests coming from webView, so you have to check attributes assotiated with incoming request and repack it into new request and send it again via your own connection. Since you are in stack, your request immidiatly comes to you again and you have to ignore it. So it goes down protocol stack to real HTTP protocol implementation, since your request is not athenticated you'll get authenticaiton request. And after authenticaiton you'll get a real response from server, so you repack response and reply to original request received from webView and that's it.

Don;t try to create new requests or responses bodies, you have to just resend them. The final code would be aproximetly 30-40 lines of code and it is quite simple, but requires a lot of debuging and tetsing.

Unfortunatlly I cannot provide code here, since I am assigned to different project already, I just wanted to say that my post is wrong way, it stucks when user changes password.

Passing Login credentials into UIWebView

Presumably you're displaying a website (e.g., www.foo.com) in the UIWebView and want to pass the SID to the UIWebView to login to www.foo.com.

You'll want to set up an NSMutableURLRequest with HTMLBody and HTTPMethod set properly to achieve this. The way to pass the SID to login is via a query parameter.

var url = NSURL(string: "http://www.foo.com")

var request = NSMutableURLRequest(URL: url!)

// usually to login you send a POST with the user's credentials
request.HTTPMethod = "POST"

// this is where you would assign the SID (from a UITextView, etc.)
var sid = "1234" // getSid()

var bodyData = "SID=\(sid)"

// encode the query params as UTF8
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)

// this will load the UIWebView by sending the POST with the query string:
// http://www.foo.com/?SID=1234
webView.loadRequest(request)

How do I detect an authentication challenge from a UIWebView?

Apple now has sample code that solves this problem. It also looks like the most complete documentation of how to implement an NSURLProtocol properly.

WKWebView and authentication

The solved it in beta 3 using the function didReceiveAuthenticationChallenge in WKNavigationDelegate. I've tried it and it works perfectly

How to authenticate in UIWebView using RestKit and WSSE?

I don't see how RestKit will help if your download content is HTML. UIWebView has a loadRequest: method so you should just create an NSURLRequest and set the auth headers then pass it straight to the web view.

Clear the credentials from UIWebView

Try Code for Clear cookie of Request

NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
NSString* domainName = [cookie domain];
NSRange domainRange = [domainName rangeOfString:@"twitter"];
if(domainRange.length > 0)
{
[storage deleteCookie:cookie];
}
}

Swift - WebView HTTP Auth - Cleanest solution

I'm not entirely sure this fulfils your demands in the best way, but if you can use a WKWebView, maybe you can simply rely on the authentication challenge delegate method? See my answer here as well, the relevant code snippet would be:

func webView(webView: WKWebView, didReceiveAuthenticationChallenge 
challenge: NSURLAuthenticationChallenge,
completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {

let creds = NSURLCredential(user:"username", password:"password", persistence: NSURLCredentialPersistence.ForSession)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, creds)
}

I haven't tried it yet myself, but the documentation says the credentials should be used for the session, so additional requests resulting from links should work. Even if not, that just results for the method to be called again and you can provide the credentials once more.

This is just a rump, you'd have to get name and password from an alert or the like (also you can store the credentials more elegantly to make subsequent calls to the delegate method more elegant).

You also wrote you're using SSL, so I take it you're familiar with the App Transport Security flags (since the question title just has "HTTP" in it and not "HTTPS", which you probably want for it to work smoothly, otherwise see the question I linked).

Swift - UIWebView baseURL resulting in blank screen

Your code isn't working because the base URL isn't https://dev-moss.stpaulscatholiccollege.co.uk/, it's https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx. Try that and it should work.

Edit:

It looks like it's not working because https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx uses HTTP Basic Authentication, which you have not provided credentials for (the UIWebView makes a separate requests for resources from your one made via Alamofire, which doesn't include your credentials.) See How to do authentication in UIWebView properly?



Related Topics



Leave a reply



Submit