tags:

views:

44

answers:

1

I need to write an OpenID client for a new platform (some funny flavour of server-side javascript) and I am trying to understand the authentication sequence. I've been reading the Ruby implementation and writing tests the types of requests / responses that generates.

The initial request is on the form:

this.getBeginUrl = function(options){
    if(!options) throw("getBeginUrl requires an options hash of the form: {return_to_path:'/path/to/return?something', base:'http://server.name'}")
    if(!options.return_to_path) throw("must supply return_to_path");
    if(!options.base) throw ("must supply base url"); 
    var params = {
        'assoc_handle':getAssocHandle(),
        'ax.mode':'fetch_request',
        'claimed_id':'http://specs.openid.net/auth/2.0/identifier_select',
        'identity':'http://specs.openid.net/auth/2.0/identifier_select',
        'mode':'checkid_setup',
        'ns':'http://specs.openid.net/auth/2.0',
        'ns.ax':'http://openid.net/srv/ax/1.0',
        'ns.sreg':'http://openid.net/extensions/sreg/1.1',
        'realm':options.base,
        'return_to':options.base + options.return_to_path + '&open_id_complete=1' // Assuming the return-to url has a ? in it
    }
    if(options.required) params['sreg.required'] = options.required;
    var result = [];
    for(var e in params) result.push([escape('openid.'+e)] +"=" +escape(params[e]));
    return openid_url + '?' + result.join('&'); // Assuming the openid url didn't have a ? in it already 
}

So my question is about how to create this assoc_handle field and how to verify what comes back from the openid server. And something about nonces.

The response when I send this request is of the form:

'openid.op_endpoint':'https://login.launchpad.net/+openid',           
    'openid.signed':'assoc_handle,claimed_id,identity,invalidate_handle,mode,ns,ns.sreg,op_endpoint,response_nonce,return_to,signed,sreg.nickname',
   'openid.sig':'HMeqwtQ8vG4aNOvRFVSnuOfWv30=',
   'openid.response_nonce':'2010-09-29T10:50:31Z3nPoQ3',
   'open_id_complete':'1',
   'openid.claimed_id':'https://login.launchpad.net/+id/ref466F',
   'foo':'bar',
   'openid.assoc_handle':'{HMAC-SHA1}{4ca319f7}{+KiTxQ==}',
   'openid.sreg.nickname':'michaelforrest',
   'openid.ns':'http://specs.openid.net/auth/2.0',
   'openid.identity':'https://login.launchpad.net/+id/ref466F',
   'openid.ns.sreg':'http://openid.net/extensions/sreg/1.1',
   'openid.mode':'id_res',
   'openid.invalidate_handle':'foo',
   'openid.return_to':'http://localhost:9000/ep/openid/?foo=bar&open_id_complete=1',

So I guess I need to understand how to verify that this response came from the original request before saving contents of the nickname field (which is all I'm really interested in verifying) somewhere.

+1  A: 

Firstly, read the specification. Secondly, read the specification. Do it a few more times, so that you have a vague idea how it works, then try to implement it, then read the spec carefully again, so that you're sure that you have not forgotten anything.

I'm not saying that because I just want to send you to a manual, but because if you miss one small detail, you might introduce a critical vulnerability in your library.

Anyway, assoc_handle is set by the provider, not by the client. Section 8 of the spec describes how to obtain the handle. Alternatively, you could simply not care about assoc handle at all, and use stateless mode (because it's simpler).

In stateless mode, in order to validate the response, you just send a request back with the parameters contained in the openid.signed field, plus openid.sig field, and openid.mode set to check_authentication.

And here's something about, as you have requested: they are unique and start with full timestamp in utc, in iso 8601 format.

By the way, you aren't interested in verifying the sreg.nickname field. You want to verify claimed_id. sreg.nickname doesn't even have to be present in the response, even if you request it.

Still, it's really important to read the spec. Merely getting it to work isn't enough.

Mewp