var relyingParty = new openid.RelyingParty( 'http://example.com/verify', // Verification URL (yours) null, // Realm (optional, specifies realm for OpenID authentication) false, // Use stateless verification false, // Strict mode []); // Optional list of extensions to enable and include var server = require('http').createServer( function(req, res){ var parsedUrl = url.parse(req.url); if(parsedUrl.pathname == '/authenticate'){ // User supplied identifier var query = querystring.parse(parsedUrl.query); var identifier = query.openid_identifier; // Resolve identifier, associate, and build authentication URL relyingParty.authenticate(identifier, false, function(error, authUrl){ if(error){ res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' }); res.end('Authentication failed: ' + error.message); }else if (!authUrl){ res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' }); res.end('Authentication failed'); }else{ res.writeHead(302, { Location: authUrl }); res.end(); } }); }else if(parsedUrl.pathname == '/verify'){ // Verify identity assertion // NOTE: Passing just the URL is also possible relyingParty.verifyAssertion(req, function(error, result){ res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' }); if(error){ res.end('Authentication failed: ' + error.message); }else{ res.end((result.authenticated ? 'Success :)' : 'Failure :(') + '\n\n' + JSON.stringify(result)); } }); }else{ // Deliver an OpenID form on all other URLs res.writeHead(200, { 'Content-Type' : 'text/html; charset=utf-8' }); res.end('' + '' + '
Login using OpenID
' + '' + '' + ''); } }); server.listen(80);
一个更复杂的例子包括扩展可以在 GitHub 库 sample.js 发现。
支持扩展
这个库是为下面的内置支持 OpenID 的扩展:
The Simple Registration (SREG) 1.1 extension is implemented as openid.SimpleRegistration.
The Attribute Exchange (AX) 1.0 extension is implemented as openid.AttributeExchange.
The OAuth 1.0 extension is implemented as openid.OAuthHybrid.
The User Interface 1.0 extension is implemented as openid.UserInterface.
The Provider Authentication Policy Extension 1.0 (PAPE) is implemented as openid.pape.
存储关联状态
为保存/加载关联状态提供了一种方法,你需要混合在 OpenID 的模块功能:
saveAssociation(provider, type, handle, secret, expiry_time_in_seconds, callback) is called when a new association is established during authentication. The callback should be called with any error as its first argument (or null if no error occured).
loadAssociation(handle, callback) is used to retrieve the association identified by handle when verification happens. The callback should be called with any error as its first argument (and null as the second argument), or an object with the keys provider, type, secret if the association was loaded successfully.
saveDiscoveredInformation(key, provider, callback) is used when saving a discovered provider. The following behavior is required:
The key parameter should be uses as a key for storing the provider - it will be used as the lookup key when loading the provider. (Currently, the key is either a claimed identifier or an OP-local identifier, depending on the OpenID context.)
When saving fails for some reason, callback(error) is called with error being an error object specifying what failed.
When saving succeeds, callback(null) is called.
loadDiscoveredInformation(key, callback) is used to load any previously discovered information about the provider for an identifier. The following behavior is required:
When no provider is found for the identifier, callback(null, null) is called (i.e. it is not an error to not have any data to return).
When loading fails for some reason, callback(error, null) is called with error being an error string specifying why loading failed.
When loading succeeds, callback(null, provider) is called with the exact provider object that was previously stored using saveDiscoveredInformation.