gnomegobjectgnome-shell-extensionsgjslibsoup

How to use Basic Auth with libsoup via Gjs


I'm trying to query github's api with a token. Github's api accepts generated tokens provided that they're sent as a basic auth header.

The API do not return HTTP 401 if the call is made without auth which means if one wants to query their api using Basic Auth, one must fill the header pre-emptively rather than doing a round trip.

I'm now trying to query the API using libsoup and Gjs.

I have noticed the SoupAuthManager has a function that seems to match perfectly what I need (soup_auth_manager_use_auth here) but can't find a way to invoke it.

This can be used to "preload" manager 's auth cache, to avoid an extra HTTP round trip in the case where you know ahead of time that a 401 response will be returned

This is what I currently use, but it does not work as the SoupAuthManager is a private object of the session; and has therefore no effect on the actual behaviour of the program

let httpSession = new Soup.Session();
let authUri = new Soup.URI(url);
authUri.set_user(this.handle);
authUri.set_password(this.token);
let message = new Soup.Message({method: 'GET', uri: authUri});

let authManager = new Soup.AuthManager();
let auth = new Soup.AuthBasic({host: 'api.github.com', realm: 'Github Api'});

authManager.use_auth(authUri, auth);
httpSession.queue_message(message, ...);

Are there other methods I could use to force Basic Auth on the first roud trip? or are there other library I could use from gjs to call github's API and force the basic auth?


Solution

  • I found the solution. To link the authorisation to the session, one can use the add_feature function. Now this is defined here but it turns out calling it directly doesn't work

    this._httpSession.add_feature(authManager)
    

    instead it seems to work if called like that:

    Soup.Session.prototype.add_feature.call(httpSession, authManager);
    

    finally, the github api rejects any call without a user agent, so I added the following:

    httpSession.user_agent = 'blah'
    

    the final code looks like:

    let httpSession = new Soup.Session();
    httpSession.user_agent = 'blah'
    let authUri = new Soup.URI(url);
    authUri.set_user(this.handle);
    authUri.set_password(this.token);
    let message = new Soup.Message({method: 'GET', uri: authUri});
    
    let authManager = new Soup.AuthManager();
    let auth = new Soup.AuthBasic({host: 'api.github.com', realm: 'Github Api'});
    
    Soup.Session.prototype.add_feature.call(httpSession, authManager);
    httpSession.queue_message(message, function() {...});