Skip to content

Commit

Permalink
Merge pull request #20 from ExWeiv/development
Browse files Browse the repository at this point in the history
Security Update
  • Loading branch information
loeiks authored May 30, 2024
2 parents 41999e4 + 4816f91 commit 610acbd
Show file tree
Hide file tree
Showing 60 changed files with 327 additions and 122 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This library enables you to integrate some popular OAuth options with your Wix w

If you are looking for something basic for your Wix site then you can install **Easy Auth** application from Wix App Market. The version in the app market is designed for basic use cases or basic users to quickly integrate providers as easy as possible.

[Official Docs](https://easy-auth-exweiv-apps.web.app/)
> [Documentation](https://easy-auth.apps.exweiv.com/)
**Currently this package handles OAuth for:**

Expand Down
35 changes: 35 additions & 0 deletions app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Easy Auth by ExWeiv Apps

This library enables you to integrate some popular OAuth options with your Wix website or with your Wix Blocks application. This package is not for basic users and designed for customization, so developers can take the skelaton and work with it to integrate the OAuth providers however they want or need.

If you are looking for something basic for your Wix site then you can install **Easy Auth** application from Wix App Market. The version in the app market is designed for basic use cases or basic users to quickly integrate providers as easy as possible.

> [Documentation](https://easy-auth.apps.exweiv.com/)
**Currently this package handles OAuth for:**

- Facebook ✅
- Google ✅
- Discord ✅
- GitHub ✅
- Steam ✅ (Read Below)

**We are planning to add:**

- Microsoft
- Twitter
- Twitch

### About Steam OAuth Process

Steam is not providing any actual oauth flow, there isn't any official API to handle auth process with Steam, instead you have openid which plays a role as another 3rd party provider to handle authentication with Steam. But main problem with that is passing state with this option is not possible. Which means a big security issue when you are dealing with auth process.

You'll have two functions, first is `redirectURL` second is `authUser` which is also possible with other providers but! issue here is as we said you can't pass a state and you won't get any token as response what you'll get is the Steam user id (a public info of any steam user) and you'll make a call to Steam web API to get the public data of user like profile photo nickname etc.

You'll need to find a way to verify logins/users like what we do with states.

---

[Kolay Gelsin](https://medium.com/the-optimists-daily/kolay-gelsin-a-turkish-expression-we-should-all-know-and-use-83fc1207ae5d) 💜

<img src="https://static.wixstatic.com/media/510eca_399a582544de4cb2b958ce934578097f~mv2.png">
16 changes: 13 additions & 3 deletions app/lib/Discord/discord.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const axios_1 = __importDefault(require("axios"));
const querystring_1 = __importDefault(require("querystring"));
const wix_secret_helpers_1 = require("@exweiv/wix-secret-helpers");
const errors_1 = __importDefault(require("../Errors/errors"));
const helpers_1 = require("../helpers");
const redirectURL = (options) => {
try {
const { client_id, redirect_uri, state, response_type, prompt, scope } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { client_id, redirect_uri, state, response_type, prompt, scope } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!redirect_uri || !client_id) {
throw Error(`${errors_1.default.prefix} ${errors_1.default.provider[3]} - client_id, redirect_uri and scope must be a valid value`);
}
Expand All @@ -33,7 +37,10 @@ const redirectURL = (options) => {
exports.redirectURL = redirectURL;
const authUser = async (options, client_secret, access_token) => {
try {
const { code, redirect_uri, grant_type, client_id, } = options;
if (typeof options !== "object" || typeof client_secret !== "string" || typeof access_token !== "string") {
throw new Error("parameter types are invalied, options is object, client_secret and access_token is must be a string!");
}
const { code, redirect_uri, grant_type, client_id, } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!access_token) {
const tokens = await (0, exports.getTokens)({
client_secret: !client_secret ? await (0, wix_secret_helpers_1.getSecretValue)("DiscordClientSecret") : client_secret,
Expand All @@ -58,8 +65,11 @@ const authUser = async (options, client_secret, access_token) => {
exports.authUser = authUser;
const getTokens = async (options) => {
try {
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const tokenParams = new URLSearchParams();
for (const [key, value] of Object.entries(options)) {
for (const [key, value] of Object.entries((0, helpers_1.copyOwnPropsOnly)(options))) {
tokenParams.append(key, value);
}
const tokens = await axios_1.default.post("https://discord.com/api/oauth2/token", tokenParams, {
Expand Down
16 changes: 13 additions & 3 deletions app/lib/Facebook/facebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const axios_1 = __importDefault(require("axios"));
const querystring_1 = __importDefault(require("querystring"));
const wix_secret_helpers_1 = require("@exweiv/wix-secret-helpers");
const errors_1 = __importDefault(require("../Errors/errors"));
const helpers_1 = require("../helpers");
const redirectURL = (options) => {
try {
const { redirect_uri, client_id, response_type, scope, state } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { redirect_uri, client_id, response_type, scope, state } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!redirect_uri || !client_id) {
throw Error(`${errors_1.default.prefix} client_id and redirect_uri must be a valid value`);
}
Expand All @@ -32,7 +36,10 @@ const redirectURL = (options) => {
exports.redirectURL = redirectURL;
const authUser = async (options, client_secret, access_token) => {
try {
const { client_id, redirect_uri, code, fields } = options;
if (typeof options !== "object" || typeof client_secret !== "string" || typeof access_token !== "string") {
throw new Error("parameter types are invalied, options is object, client_secret and access_token is must be a string!");
}
const { client_id, redirect_uri, code, fields } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!client_id || !redirect_uri) {
throw Error(`${errors_1.default.prefix} ${errors_1.default.provider[0]} - client_id and redirect_uri must be a valid value!`);
}
Expand All @@ -55,7 +62,10 @@ const authUser = async (options, client_secret, access_token) => {
exports.authUser = authUser;
const getTokens = async (options) => {
try {
const { client_id, client_secret, redirect_uri, code, fb_exchange_token, grant_type } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { client_id, client_secret, redirect_uri, code, fb_exchange_token, grant_type } = (0, helpers_1.copyOwnPropsOnly)(options);
const tokenParams = new URLSearchParams({
client_id,
client_secret: !client_secret ? await (0, wix_secret_helpers_1.getSecretValue)("GoogleClientSecret") : client_secret,
Expand Down
16 changes: 13 additions & 3 deletions app/lib/GitHub/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const axios_1 = __importDefault(require("axios"));
const wix_secret_helpers_1 = require("@exweiv/wix-secret-helpers");
const querystring_1 = __importDefault(require("querystring"));
const errors_1 = __importDefault(require("../Errors/errors"));
const helpers_1 = require("../helpers");
const redirectURL = (options) => {
try {
const { client_id, redirect_uri, state, allow_signup } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { client_id, redirect_uri, state, allow_signup } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!redirect_uri || !client_id) {
throw Error(`${errors_1.default.prefix} ${errors_1.default.provider[2]} - client_id, redirect_uri and scope must be a valid value`);
}
Expand All @@ -31,7 +35,10 @@ const redirectURL = (options) => {
exports.redirectURL = redirectURL;
const authUser = async (options, client_secret, access_token) => {
try {
const { client_id, code, redirect_uri, repository_id } = options;
if (typeof options !== "object" || typeof client_secret !== "string" || typeof access_token !== "string") {
throw new Error("parameter types are invalied, options is object, client_secret and access_token is must be a string!");
}
const { client_id, code, redirect_uri, repository_id } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!access_token) {
const tokens = await (0, exports.getTokens)({
client_secret: !client_secret ? await (0, wix_secret_helpers_1.getSecretValue)("GitHubClientSecret") : client_secret,
Expand All @@ -58,8 +65,11 @@ const authUser = async (options, client_secret, access_token) => {
exports.authUser = authUser;
const getTokens = async (options) => {
try {
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const tokenParams = new URLSearchParams();
for (const [key, value] of Object.entries(options)) {
for (const [key, value] of Object.entries((0, helpers_1.copyOwnPropsOnly)(options))) {
tokenParams.append(key, value);
}
const tokens = await axios_1.default.post("https://github.com/login/oauth/access_token", tokenParams, {
Expand Down
16 changes: 13 additions & 3 deletions app/lib/Google/google.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const axios_1 = __importDefault(require("axios"));
const wix_secret_helpers_1 = require("@exweiv/wix-secret-helpers");
const querystring_1 = __importDefault(require("querystring"));
const errors_1 = __importDefault(require("../Errors/errors"));
const helpers_1 = require("../helpers");
const redirectURL = (options) => {
try {
const { redirect_uri, client_id, response_type, scope, state, access_type, prompt } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { redirect_uri, client_id, response_type, scope, state, access_type, prompt } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!redirect_uri || !client_id) {
throw Error(`${errors_1.default.prefix} ${errors_1.default.provider[1]} - client_id, redirect_uri and scope must be a valid value`);
}
Expand All @@ -34,7 +38,10 @@ const redirectURL = (options) => {
exports.redirectURL = redirectURL;
const authUser = async (options, client_secret, access_token) => {
try {
const { client_id, redirect_uri, code, grant_type } = options;
if (typeof options !== "object" || typeof client_secret !== "string" || typeof access_token !== "string") {
throw new Error("parameter types are invalied, options is object, client_secret and access_token is must be a string!");
}
const { client_id, redirect_uri, code, grant_type } = (0, helpers_1.copyOwnPropsOnly)(options);
if (!client_id || !redirect_uri || !code) {
throw Error(`${errors_1.default.prefix} ${errors_1.default.provider[1]} - client_id, redirect_uri and code must be a valid value!`);
}
Expand All @@ -58,7 +65,10 @@ const authUser = async (options, client_secret, access_token) => {
exports.authUser = authUser;
const getTokens = async (options) => {
try {
const { client_id, client_secret, code, grant_type, redirect_uri, refresh_token } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { client_id, client_secret, code, grant_type, redirect_uri, refresh_token } = (0, helpers_1.copyOwnPropsOnly)(options);
const tokenParams = new URLSearchParams({
grant_type: !grant_type ? "authorization_code" : grant_type,
client_secret: !client_secret ? await (0, wix_secret_helpers_1.getSecretValue)("GoogleClientSecret") : client_secret,
Expand Down
11 changes: 9 additions & 2 deletions app/lib/Steam/steam.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ const axios_1 = __importDefault(require("axios"));
const wix_secret_helpers_1 = require("@exweiv/wix-secret-helpers");
const querystring_1 = __importDefault(require("querystring"));
const errors_1 = __importDefault(require("../Errors/errors"));
const helpers_1 = require("../helpers");
const redirectURL = (options) => {
try {
const { realm, redirect_uri } = options;
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}
const { realm, redirect_uri } = (0, helpers_1.copyOwnPropsOnly)(options);
const rootURL = "https://steamcommunity.com/openid/login";
const urlOptions = {
"openid.ns": "http://specs.openid.net/auth/2.0",
Expand All @@ -29,7 +33,10 @@ const redirectURL = (options) => {
exports.redirectURL = redirectURL;
const authUser = async (options, client_secret) => {
try {
const { steamId } = options;
if (typeof options !== "object" || typeof client_secret !== "string") {
throw new Error("parameter types are invalied, options is object and client_secret is must be a string!");
}
const { steamId } = (0, helpers_1.copyOwnPropsOnly)(options);
const steamUserResponse = await axios_1.default.get(`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${!client_secret ? await (0, wix_secret_helpers_1.getSecretValue)("SteamClientSecret") : client_secret}&steamids=${steamId}`);
const result = steamUserResponse.data;
if (!(result && result.response && Array.isArray(result.response.players) && result.response.players.length > 0)) {
Expand Down
33 changes: 33 additions & 0 deletions app/lib/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyOwnPropsOnly = void 0;
function copyOwnPropsOnly(src) {
const result = Object.create(null);
function copyObject(value) {
if (isPlainObject(value)) {
return copyOwnPropsOnly(value);
}
else {
return value;
}
}
for (const key of Object.getOwnPropertyNames(src)) {
if (key !== "__proto__" || "constructor" || "prototype") {
if (typeof src[key] === "object") {
result[key] = copyObject(src[key]);
}
else {
result[key] = src[key];
}
}
}
return result;
}
exports.copyOwnPropsOnly = copyOwnPropsOnly;
function isPlainObject(value) {
if (typeof value !== 'object' || value === null)
return false;
if (Array.isArray(value))
return false;
return value.constructor === Object;
}
4 changes: 2 additions & 2 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@exweiv/easy-auth",
"version": "0.2.2",
"version": "0.3.0",
"description": "Integrate popular OAuth apps with your Wix website easily.",
"main": "./lib/index.js",
"scripts": {
Expand All @@ -27,15 +27,15 @@
"url": "[email protected]:ExWeiv/easy-auth.git",
"type": "git"
},
"homepage": "https://apps.exweiv.com/",
"homepage": "https://easy-auth.apps.exweiv.com/",
"bugs": {
"url": "https://github.com/ExWeiv/easy-auth/issues",
"email": "[email protected]"
},
"contributors": [
{
"name": "Enes Bekar",
"url": "https://github.com/l0eix"
"url": "https://github.com/loeiks"
}
],
"engines": {
Expand All @@ -53,6 +53,5 @@
"@types/uuid": "^9.0.8",
"typedoc": "^0.25.12",
"typedoc-plugin-extras": "^3.0.0"
},
"readme": "https://raw.githubusercontent.com/ExWeiv/easy-auth/main/README.md"
}
}
19 changes: 16 additions & 3 deletions app/src/Discord/discord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ import querystring from 'querystring';
import { getSecretValue } from '@exweiv/wix-secret-helpers';
// Internal Imports
import errCodes from '../Errors/errors';
import { copyOwnPropsOnly } from '../helpers';

export const redirectURL = (options: discord.RedirectURLOptions): string => {
try {
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}

const {
client_id,
redirect_uri,
state,
response_type,
prompt,
scope
} = options;
} = copyOwnPropsOnly(options);

if (!redirect_uri || !client_id) {
throw Error(`${errCodes.prefix} ${errCodes.provider[3]} - client_id, redirect_uri and scope must be a valid value`);
Expand All @@ -43,12 +48,16 @@ export const redirectURL = (options: discord.RedirectURLOptions): string => {

export const authUser = async (options: discord.AuthOptions, client_secret?: string, access_token?: string): Promise<AuthResponse> => {
try {
if (typeof options !== "object" || typeof client_secret !== "string" || typeof access_token !== "string") {
throw new Error("parameter types are invalied, options is object, client_secret and access_token is must be a string!");
}

const {
code,
redirect_uri,
grant_type,
client_id,
} = options;
} = copyOwnPropsOnly(options);

if (!access_token) {
const tokens = await getTokens({
Expand All @@ -75,9 +84,13 @@ export const authUser = async (options: discord.AuthOptions, client_secret?: str

export const getTokens = async (options: discord.TokensOptions): Promise<discord.TokensResponse> => {
try {
if (typeof options !== "object") {
throw new Error("parameter type is invalied, options must be an object!");
}

const tokenParams = new URLSearchParams();

for (const [key, value] of Object.entries(options)) {
for (const [key, value] of Object.entries(copyOwnPropsOnly(options))) {
tokenParams.append(key, value);
}

Expand Down
Loading

0 comments on commit 610acbd

Please sign in to comment.