Jacolack Jacolack - 1 year ago 122
iOS Question

NSURLSession Authentication

I tried to use the swift code found here on the website found here, but the response is html code with the two errors: "You must enter a password!" and "You must enter a User name!" I am new to NSURLSession and tried to change the string for authentication but nothing worked to change the response. Here is my code:

let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let userPasswordString = "username@gmail.com:password"
let userPasswordData = userPasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = userPasswordData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
let authString = "Basic \(base64EncodedCredential)"
config.HTTPAdditionalHeaders = ["Authorization" : authString]
let session = NSURLSession(configuration: config)
var running = false
let url = NSURL(string: "https://hac.chicousd.org/")
let task = session.dataTaskWithURL(url!) {
(let data, let response, let error) in
if (response as? NSHTTPURLResponse) != nil {
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
running = false

running = true

while running {

And this is in the console response:

<!-- Start Error box -->
<div id="errorContainer" class="alert alert-danger" style="display:none;">
<button id="portalCloseError" type="button" class="close"> &times;</button>
<span id="errorMessage" class="error" data-pw-error="You must enter a password!" data-username-error="You must enter a User Name!"></span>
</div> <!-- End Error box -->

Answer Source

There are 2 ways to sign in to a website: HTTP Authorization and form. Most website uses the later, more user-friendly login form. HTTP Authorization is only used when the website expects to interact with a user program (no, browsers don't count here).

Before you code, you need to scout the website for what form data it sends, as knowing is half the battle:

  1. Visit the school website and press Cmd + Opt + C to open the Developer's Console.
  2. Click the Network tab.
  3. Do not close this console. Go back to the website and enter your username and password as usual.

Observe what data the page sends:

Developer Console

In plain text:

checkCookiesEnabled         true
checkMobileDevice           false
checkStandaloneMode         false
checkTabletDevice           false
portalAccountUsername       email
portalAccountPassword       password

So the username is delivered in a field called portalAccountUsername and password in portalAccountPassword. The other fields may or may not be important.

And now you can write your code:

@IBAction func login(sender: AnyObject) {
    let url = NSURL(string: "https://hac.chicousd.org/LoginParent.aspx")!

    // The form parameters
    let parameters = [
        "checkCookiesEnabled": "true",
        "checkMobileDevice": "false",
        "checkStandaloneMode": "false",
        "checkTabletDevice": "false",
        "portalAccountUsername": "username",
        "portalAccountPassword": "password"

    let bodyString = parameters
                        .map { $0 + "=" + $1 }

    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.HTTPBody = bodyString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
        guard error == nil else {
        guard let data = data else {
            print("empty data")

        // This is the HTML source of the landing page after login
        let html = String(data: data, encoding: NSUTF8StringEncoding)

For some reasons, I couldn't make the request until I disabled App Transport Security. Maybe resources on that website come from non-HTTPS domains.