If somebody’s interested in how to do login now, and how to verify a token from SSO in NodeJS, here is an example code I use on my site.
My login process consists of 2 parts. First one is an initial stage, and, actually, here I just redirect people to login.eveonline.com.
const params = new URLSearchParams({
response_type: 'code',
redirect_uri: encodeURI(eveSsoRedirectUri),
client_id: eveSsoClientId,
scope: '',
state,
});
throw new RedirectTemporarily(`https://login.eveonline.com/v2/oauth/authorize?${params.toString()}`);
The eveSsoRedirectUri
is the “Callback Url” from my app settings.
Nothing complex here, and, comparing to V1 scheme, you only change oauth/authorize
to v2/oauth/authorize
.
Second part is the page to where you are redirected after successful auth on login.eveonline.com (the page you have set as “Callback Url” for you app). In this page I call tokenFromEveSsoCode
function passing received code
as a param.
async function tokenFromEveSsoCode(code) {
// If you use jose prior to v4, import them that way:
// const {importJWK} = require('jose/key/import');
// const {jwtVerify} = require('jose/jwt/verify');
// For jose version 4+
const {importJWK, jwtVerify} = require('jose');
const eveSsoClientId = 'Application Settings → Client ID';
const eveSsoSecretKey = 'Application Settings → Secret Key';
const params = new URLSearchParams({grant_type: 'authorization_code', code});
const authInfo = Buffer.from(`${eveSsoClientId}:${eveSsoSecretKey}`).toString('base64');
const [tokenInfo, signatures] = await Promise.all([
simpleJsonRequest(
'https://login.eveonline.com/v2/oauth/token',
params.toString(),
'POST',
{"Authorization": `Basic ${authInfo}`}
),
simpleJsonRequest('https://login.eveonline.com/oauth/jwks'),
]);
if (!isObject(signatures)) {
console.log(signatures);
throw new Error('Incorrect JWKS signatures from EVE Online (printed above)');
}
if (!signatures.hasOwnProperty('keys')) {
console.log(signatures);
throw new Error('Cannot find keys in JWKS signatures from EVE Online (printed above)');
}
const alg = 'RS256';
let jwkSetKey = null;
signatures.keys.map(key => {
if (key.alg === alg) {
jwkSetKey = key;
}
});
if (!jwkSetKey) {
console.log(signatures);
throw new Error(`Cannot find the ${alg} algo in JWKS signatures from EVE Online (printed above)`);
}
const publicKey = await importJWK(jwkSetKey);
const {payload} = await jwtVerify(tokenInfo['access_token'], publicKey, {
issuer: 'login.eveonline.com',
});
tokenInfo.payload = payload;
return tokenInfo;
}
I use the “jose” library to verify token, and I’ve found it on https://jwt.io/ which contains a lot of links to JWT libraries for different tastes and languages. (EVE Online developers suggested to use the site in the devblog, but I’ve found the site even before this devblog was published.)
The simpleJsonRequest
function you can notice in code, is my internal HTTP helper, and I mention it just to describe that: 1st parameter is target URL, 2nd one is POST data (and when I pass it this way — like a string — it always sends data as application/x-www-form-urlencoded
), 3rd parameter is a request method, and 4th — additional headers. As you can see, when you fetch token from https://login.eveonline.com/v2/oauth/token
, you need to provide some auth info in header, and it’s just Base64-encoded [Client ID][colon][Secret Key]
string — pretty easy to create it.
To verify token, I fetch EVE Online signatures from https://login.eveonline.com/oauth/jwks
, pick a signature which use RS256
, and convert it to public key by using jose’s function importJWK
. After that I use jose’s function jwtVerify
to both verify token and convert it to JSON payload (the payload contains all needed info like character ID which was used on login.eveonline.com to allow your auth, expiration info, and etc.).
So, to summarize things, if you was verifying tokens before Nov 1st by using special oauth/verify
verification endpoint, new way of verifying tokens does not reduce amount of HTTP calls (but it’s possible to reduce it by caching https://login.eveonline.com/oauth/jwks
data somewhere in your code).
Also, if you do not want to verify token, you just can convert tokenInfo['access_token']
(which presented as a Base64-encoded string) to JSON data manually (sorry, I forgot how I did that when I was debugging things, but you may want to check this SO thread for needed info: https://stackoverflow.com/questions/52863051/decode-jwt-token-in-node-without-library).
Hope this short guide will help you to convert your code to V2.