Jamil Ahmed
Jamil Ahmed

Reputation: 35

Calling rest server from mobile app

Following on from https://lists.hyperledger.org/g/composer/message/91

I have adapted the methodology described by Caroline Church in my IOS app. Again I can authenticate with google but still get a 401 authorization error when POSTing.

I have added the withCredentials parameter to the http header in my POST request.

does the rest server pass back the token in cookie ? I don't receive anything back from the rest server.

where does the withCredentials get the credentials from ?

COMPOSER_PROVIDERS as follows

COMPOSER_PROVIDERS='{
    "google": {
        "provider": "google",
        "module": "passport-google-oauth2",
        "clientID": "93505970627.apps.googleusercontent.com",
        "clientSecret": "",
        "authPath": "/auth/google",
        "callbackURL": "/auth/google/callback",
        "scope": "https://www.googleapis.com/auth/plus.login",
        "successRedirect": "myAuth://",
        "failureRedirect": "/"
    }
}'

the successRedirect points back to my App. After successfully authenticating I return to the App.

Upvotes: 1

Views: 490

Answers (3)

Jamil Ahmed
Jamil Ahmed

Reputation: 35

func getRestToken(code: String) {        
    let tokenURL = "http://localhost:3000/auth/google/callback?code=" + code

    let url = URL(string:tokenURL);

    var request = URLRequest(url: url!);

    request.httpMethod = "GET";

    request.setValue("localhost:3000", forHTTPHeaderField: "Host");

    request.setValue("text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8", forHTTPHeaderField: "Accept");
    request.setValue("1", forHTTPHeaderField: "Upgrade-Insecure-Requests");

    request.httpShouldHandleCookies = true;
    request.httpShouldUsePipelining = true;

    let session = URLSession.init(configuration: .default);
    session.configuration.httpCookieAcceptPolicy = .always;
    session.configuration.httpShouldSetCookies=true;
    session.configuration.httpCookieStorage = HTTPCookieStorage.shared;

    let task = session.dataTask(with: request) { (data, response, error) in
            var authCookie: HTTPCookie? = nil;
            let sharedCookieStorage = HTTPCookieStorage.shared.cookies;

            // test for access_token
            for cookie in sharedCookieStorage! {
                if cookie.name == "access_token"
                {
                    print(“Received access token”)
                }
            }

            guard error == nil else {
                print("HTTP request failed \(error?.localizedDescription ?? "ERROR")")
                return
            }
            guard let response = response as? HTTPURLResponse else {
                print("Non-HTTP response")
                return
            }
            guard let data = data else {
                print("HTTP response data is empty")
                return
            }

            if response.statusCode != 200 {
                // server replied with an error
                let responseText: String? = String(data: data, encoding: String.Encoding.utf8)

                if response.statusCode == 401 {
                    // "401 Unauthorized" generally indicates there is an issue with the authorization
                    print("Error 401");
                } else {
                    print("HTTP: \(response.statusCode), Response: \(responseText ?? "RESPONSE_TEXT")")
                }
                return
            }

        }

    task.resume()

}

Upvotes: 1

Jamil Ahmed
Jamil Ahmed

Reputation: 35

Got this working now. The App first authenticates with google then exchanges the authorization code with the rest server.

The Rest server COMPOSER_PROVIDERS needs to be changed to relate back to the app. clientID is the apps ID in google, callbackURL and successRedirect are reversed_clientID://

The App calls http://localhost:3000/auth/google/callback with the authorization code as a parameter.

this call will fail, but an access_token cookie is written back containing the access token required for the rest server.

The user id of the logged in user is not passed back, when exchanging the code for a token with google we get back a JWT with the details of the logged in user. We need this back from the rest server as well as the token. Is there any way to get this ?

changing the COMPOSER_PROVIDERS means that the explorer interface to the Rest server no longer works.

Upvotes: 1

Paul O'Mahony
Paul O'Mahony

Reputation: 6740

have you authorised the redirect URI in your Google OAUTH2 configuration ?

This determines where the API server redirects the user, after the user completes the authorization flow. The value must exactly match one of the redirect_uri values listed for your project in the API Console. Note that the http or https scheme, case, and trailing slash ('/') must all match.

This is an example of an Angular 5 successfully using it Angular 5, httpclient ignores set cookie in post in particular the answer at the bottom Scope controls the set of resources and operations that an access token permits. During the access-token request, your application sends one or more values in the scope parameter.

see https://developers.google.com/identity/protocols/OAuth2

The withCredentials option is set, in order to create a cookie, to pass the authentication token, to the REST server.

Finally this resource may help you https://hackernoon.com/adding-oauth2-to-mobile-android-and-ios-clients-using-the-appauth-sdk-f8562f90ecff

Upvotes: 0

Related Questions