Compare commits
7 Commits
9.3.0-alph
...
alpha
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b93c618bc2 | ||
| ce5dde808a | |||
| 78b803abe7 | |||
| ef1d5f44e7 | |||
| ca873bc238 | |||
| c0ef385a7b | |||
|
|
d186471d45 |
17
package-lock.json
generated
17
package-lock.json
generated
@@ -81,7 +81,7 @@
|
||||
"deep-diff": "1.0.2",
|
||||
"eslint": "9.27.0",
|
||||
"eslint-plugin-expect-type": "0.6.2",
|
||||
"eslint-plugin-unused-imports": "4.3.0",
|
||||
"eslint-plugin-unused-imports": "4.4.1",
|
||||
"form-data": "4.0.5",
|
||||
"globals": "16.2.0",
|
||||
"graphql-tag": "2.12.6",
|
||||
@@ -9916,14 +9916,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unused-imports": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.3.0.tgz",
|
||||
"integrity": "sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==",
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz",
|
||||
"integrity": "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0",
|
||||
"eslint": "^9.0.0 || ^8.0.0"
|
||||
"eslint": "^10.0.0 || ^9.0.0 || ^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
@@ -29458,9 +29457,9 @@
|
||||
}
|
||||
},
|
||||
"eslint-plugin-unused-imports": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.3.0.tgz",
|
||||
"integrity": "sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==",
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz",
|
||||
"integrity": "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
"deep-diff": "1.0.2",
|
||||
"eslint": "9.27.0",
|
||||
"eslint-plugin-expect-type": "0.6.2",
|
||||
"eslint-plugin-unused-imports": "4.3.0",
|
||||
"eslint-plugin-unused-imports": "4.4.1",
|
||||
"form-data": "4.0.5",
|
||||
"globals": "16.2.0",
|
||||
"graphql-tag": "2.12.6",
|
||||
|
||||
@@ -19,10 +19,12 @@ import linkedin from './linkedin';
|
||||
const meetup = require('./meetup');
|
||||
import mfa from './mfa';
|
||||
import microsoft from './microsoft';
|
||||
const nintendo = require("./nintendo");
|
||||
import oauth2 from './oauth2';
|
||||
const phantauth = require('./phantauth');
|
||||
import qq from './qq';
|
||||
import spotify from './spotify';
|
||||
const steam = require("./steam");
|
||||
import twitter from './twitter';
|
||||
const vkontakte = require('./vkontakte');
|
||||
import wechat from './wechat';
|
||||
@@ -47,9 +49,11 @@ const providers = {
|
||||
linkedin,
|
||||
meetup,
|
||||
mfa,
|
||||
nintendo,
|
||||
google,
|
||||
github,
|
||||
twitter,
|
||||
steam,
|
||||
spotify,
|
||||
anonymous,
|
||||
digits,
|
||||
|
||||
99
src/Adapters/Auth/nintendo.js
Normal file
99
src/Adapters/Auth/nintendo.js
Normal file
@@ -0,0 +1,99 @@
|
||||
var Parse = require('parse/node').Parse;
|
||||
const { URL } = require('url');
|
||||
var jwt = require('jsonwebtoken');
|
||||
var jwksClient = require('jwks-rsa');
|
||||
|
||||
// Returns a promise that fulfills iff this nsa id token is valid
|
||||
function validateAuthData(authData, authOptions) {
|
||||
//console.log("going to validate for nintendo");
|
||||
//console.log(authData);
|
||||
if ("token" in authData) {
|
||||
try {
|
||||
var token = authData["token"];
|
||||
var decoded = jwt.decode(token, {complete: true});
|
||||
var header = decoded.header;
|
||||
|
||||
// console.log("got nsa id token, header is:");
|
||||
// console.log(header);
|
||||
// console.log("full decoded token is:");
|
||||
// console.log(decoded);
|
||||
|
||||
if (!('alg' in header) || header['alg'] != "RS256") {
|
||||
error("No algorithm specified or it didn't match expected value 'RS256'");
|
||||
}
|
||||
|
||||
if (!('kid' in header) || !('jku' in header)) {
|
||||
error("Either 'kid' or 'jku' value not present in token.");
|
||||
}
|
||||
var jwk_name = header['kid'];
|
||||
var jku = header['jku'];
|
||||
|
||||
if (!isValidJKU(jku)) {
|
||||
error("JKU url in token isn't valid");
|
||||
}
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var client = jwksClient({
|
||||
jwksUri: jku
|
||||
});
|
||||
function getKey(header, callback) {
|
||||
client.getSigningKey(header.kid, function (err, key) {
|
||||
var signingKey = key.publicKey || key.rsaPublicKey;
|
||||
callback(null, signingKey);
|
||||
});
|
||||
}
|
||||
var options = {};
|
||||
jwt.verify(token, getKey, options, function(err, decoded) {
|
||||
// console.log("verfied jwt, decoded value is:");
|
||||
// console.log(decoded);
|
||||
if (err != null) {
|
||||
reject("Error verifying jwt: " + err.message);
|
||||
return;
|
||||
}
|
||||
if (!new URL(decoded.iss).hostname.endsWith("nintendo.com")) {
|
||||
reject("iss claim in token is not a nintendo server");
|
||||
return;
|
||||
}
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
if (Number.parseInt(decoded.iat) > (now + 10000)) {
|
||||
reject("iat value is not in the past");
|
||||
return;
|
||||
}
|
||||
if (Number.parseInt(decoded.exp) < (now - 10000)) {
|
||||
reject("exp value is not in the future");
|
||||
return;
|
||||
}
|
||||
if (decoded.nintendo.ai != authOptions.serverId) {
|
||||
reject("application id does not match our id");
|
||||
return;
|
||||
}
|
||||
resolve(decoded);
|
||||
});
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
error('Error authenticating NSA id token: ' + e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error('No token found in the request');
|
||||
}
|
||||
}
|
||||
|
||||
// steam auth bundles the app id in the auth data so don't validate seperately
|
||||
function validateAppId() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function isValidJKU(jku) {
|
||||
// todo - validate this properly?
|
||||
return new URL(jku).hostname.endsWith("nintendo.com");
|
||||
}
|
||||
|
||||
function error(message) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, message);
|
||||
}
|
||||
module.exports = {
|
||||
validateAppId,
|
||||
validateAuthData
|
||||
};
|
||||
92
src/Adapters/Auth/steam.js
Normal file
92
src/Adapters/Auth/steam.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Parse Server authentication adapter for Steam.
|
||||
*
|
||||
* @class SteamAdapter
|
||||
* @param {Object} options - The adapter configuration options.
|
||||
*
|
||||
* @description
|
||||
* ## Parse Server Configuration
|
||||
* To configure Parse Server for Steam authentication, use the following structure:
|
||||
* ```json
|
||||
* {
|
||||
* "auth": {
|
||||
* "steam": {
|
||||
* "appId": "your-app-id",
|
||||
* "webApiKey": "your-web-api-key"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The adapter requires the following `authData` fields:
|
||||
*
|
||||
* ## Auth Payloads
|
||||
* ```json
|
||||
* {
|
||||
* "steam": {
|
||||
* "??": "??"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see {@link https://partner.steamgames.com/doc/api/ISteamUser#GetAuthTicketForWebApi Steam Web API docs}
|
||||
*/
|
||||
|
||||
var Parse = require('parse/node').Parse;
|
||||
const https = require('https');
|
||||
const querystring = require('querystring');
|
||||
|
||||
|
||||
// Returns a promise that fulfills iff this application ticket is valid
|
||||
function validateAuthData(authData, authOptions) {
|
||||
if ("auth_ticket" in authData) {
|
||||
//console.log("Authenticate steam user using web api and auth ticket");
|
||||
return callSteamWebApi(authData.auth_ticket, authOptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// steam auth bundles the app id in the auth data so don't validate seperately
|
||||
function validateAppId() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function callSteamWebApi(auth_ticket, authOptions) {
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
// GET parameters
|
||||
const parameters = {
|
||||
key: authOptions.webApiKey,
|
||||
appid: authOptions.appId, // could try the demo id too, but we know that doesn't allow online play so don't worry for now
|
||||
ticket: auth_ticket,
|
||||
identity: authOptions.serverId
|
||||
}
|
||||
|
||||
const get_request_args = querystring.stringify(parameters);
|
||||
|
||||
const options = {
|
||||
host: "partner.steam-api.com",
|
||||
path: "/ISteamUserAuth/AuthenticateUserTicket/v1/?" + get_request_args,
|
||||
headers : {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
|
||||
var request = https.request(options, (response) => {
|
||||
//console.log("Steam web auth sucess");
|
||||
resolve();
|
||||
});
|
||||
|
||||
request.on('error', (error) => {
|
||||
//console.log(error.message);
|
||||
reject('The Steam web api could not authenticate the user with the given auth ticket');
|
||||
});
|
||||
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateAppId,
|
||||
validateAuthData
|
||||
};
|
||||
Reference in New Issue
Block a user