2010-09-29 5 views
3

J'ai besoin d'écrire un client OpenID pour une nouvelle plate-forme (une saveur amusante de javascript côté serveur) et j'essaie de comprendre la séquence d'authentification. J'ai lu l'implémentation et l'écriture de Ruby pour tester les types de requêtes/réponses générées.Comment implémenter un client OpenID à partir de zéro?

La demande initiale est sur la forme:

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 
} 

Donc ma question est de savoir comment créer ce champ assoc_handle et comment vérifier ce qui revient du serveur OpenID. Et quelque chose à propos de nonces.

La réponse quand j'envoie cette demande est de la forme:

'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', 

donc je suppose que je dois comprendre comment vérifier que cette réponse est venue de la demande initiale avant d'enregistrer le contenu du champ pseudo (qui est tout ce que je suis vraiment intéressé à vérifier) ​​quelque part.

Répondre

5

Premièrement, lisez specification. Deuxièmement, lisez le specification. Faites-le quelques fois de plus, de sorte que vous ayez une idée vague de comment cela fonctionne, puis essayez de l'implémenter, puis relisez attentivement la spécification, de sorte que vous soyez sûrs que vous n'avez rien oublié. Je ne dis pas cela parce que je veux juste vous envoyer un manuel, mais parce que si vous manquez un petit détail, vous pourriez introduire une vulnérabilité critique dans votre bibliothèque.

Quoi qu'il en soit, assoc_handle est définie par le fournisseur et non par le client. La section 8 de la spécification décrit comment obtenir le handle. Alternativement, vous pouvez simplement ne pas se soucier de la poignée assoc du tout, et utiliser le mode sans état (parce que c'est plus simple).

En mode sans état, afin de valider la réponse, vous suffit d'envoyer une demande de retour avec les paramètres contenus dans le champ openid.signed, plus openid.sig champ, et openid.mode ensemble à check_authentication. Et voici quelque chose, comme vous l'avez demandé: ils sont uniques et commencent par l'horodatage complet dans utc, au format ISO 8601. Par ailleurs, vous ne souhaitez pas vérifier le champ sreg.nickname. Vous voulez vérifier claimed_id. sreg.nickname n'a même pas besoin d'être présent dans la réponse, même si vous le demandez.

Encore, c'est vraiment important de lire les spécifications. Simplement le faire travailler ne suffit pas.

Questions connexes