OAuth: Argument does not respect defined limits

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want my application to successfully log a user in.
  2. What is the issue? Include screenshots / videos if possible!
    “Argument does not respect the defined limits”
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried using the sample code but it didn’t work. The code couldn’t even import the values from the env file.

I have attached the relevant pieces of code along with the explorer view.


Code_ANurDogmjP





app.js
const crypto = require('crypto');
const axios = require('axios')
const express = require('express')

const app = express()

app.use(express.static('public'))

let redirectURI = "https://holocafe.nwygo.com/authorize" // Note to self: Would redirect them to /authorize?code={code} | I can then access the code using params with express or smth ig
function base64URLEncode(str) {
    return str.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}

console.log("1")

function sha256(buffer) {
    return crypto.createHash('sha256').update(buffer).digest(`base64`);
}
var code_verifier = base64URLEncode(crypto.randomBytes(32));
// generate a challenge from the code verifier
var code_challenge = base64URLEncode(sha256(code_verifier));

console.log("2")

console.log("3")
function exchangeWithCode(code) {
    const data = new URLSearchParams();
    data.append('grant_type', "authorization_code");
    data.append('client_id', process.env["clientID"]);
    data.append('client_secret', process.env["clientSecret"]);
    data.append('code', code)

    axios.post('https://apis.roblox.com/oauth/v1/token', data, {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    })
        .then(response => {
            return response
        })
        .catch(error => {
            console.error(error);
            return `Failed. Error: ${error}`
        });
}
console.log("4")
function exchangeWithRefreshToken(refreshToken) {
    const data = new URLSearchParams();
    data.append('grant_type', "authorization_code");
    data.append('client_id', process.env["clientID"]);
    data.append('client_secret', process.env["clientSecret"]);
    data.append('refresh_token', refreshToken)

    axios.post('https://apis.roblox.com/oauth/v1/token', data, {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    })
        .then(response => {
            return response
        })
        .catch(error => {
            console.error(error);
            return `Failed. Error: ${error}`
        });
}
console.log("5")
function getUserInfo(authCode) { // https://create.roblox.com/docs/cloud/reference/oauth2#get-v1userinfo
    axios.get('https://apis.roblox.com/oauth/v1/userinfo', {
        headers: {
            'Authorization': `Bearer ${authCode}`
        }
    })
        .then(response => {
            return response
        })
        .catch(error => {
            console.error(error);
        });
}
console.log("6")

console.log("7")

app.get('/authorize', (req, res) => {
    if (req.query.method = "code") {
        if (req.query.code) {
            // Successfully authorized. Run code to exchange for token
            let request = exchangeWithCode(req.query.code)
            let token = request.query.access_token
            let refreshToken = request.query.refresh_token

            let userInfo = getUserInfo(token)
            // Add code to store new refreshToken

            res.send({userInfo})
        } else {
            console.log(`Failed to authorize. Error: ${req.error}. Description: ${req.error_description}. State: ${req.state}`)
            res.send("Failed")
        }
    } else if (req.query.method == "rf") {
        if (req.query.rf) {
            // Successfully authorized. Run code to exchange for token
            let request = exchangeWithRefreshToken(req.query.rf)
            let token = request.query.access_token
            let refreshToken = request.query.refresh_token

            // Add code to store new refreshToken


        } else {
            console.log(req)
            console.log(`Failed to authorize. Error: ${req.error}. Description: ${req.error_description}. State: ${req.state}`)
            res.send("Failed")
        }
    } else {
        res.send("Invalid method")
    }
})
console.log("8")
app.get('/logout', (req, res) => {
    // will do later -- https://create.roblox.com/docs/cloud/reference/oauth2#post-v1tokenrevoke
})

console.log("9")

app.listen(25024)

console.log("10")
script.js
var scopes = ["openid", "profile", "group:read"]; // Replace with all the scopes

function generateRandomString(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

function base64URLEncode(str) {
    return btoa(str)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}

async function sha256(plain) {
    // Returns the SHA-256 hash of the input string
    const encoder = new TextEncoder();
    const data = encoder.encode(plain);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
    return hashHex;
  }

// Generate code verifier and challenge
var code_verifier = generateRandomString(128);
var code_challenge = base64URLEncode(sha256(code_verifier));

let redirectURI = "https://holocafe.nwygo.com/authorize" // Note to self: Would redirect them to /authorize?code={code} | I can then access the code using params with express or smth ig

var OAuthURL = "https://apis.roblox.com/oauth/v1/authorize" +
    "?client_id=2969482479946332042" +
    "&code_challenge=" + code_challenge +
    "&code_challenge_method=S256" +
    "&redirect_uri=" + redirectURI +
    "&scope=" + scopes.join("%20") +
    "&response_type=code" +
    "&state=abc123";

console.log("OAuthURL:", OAuthURL);

let authButton = document.getElementById('authButton')
authButton.href = OAuthURL

Please help :pray:

1 Like

Your redirect url is not url escaped so it messes up your url paramaters
Use this encodeURIComponent() - JavaScript | MDN

1 Like

Is this how it should be done?

1 Like

Yeah that would work. If it doesnt work, can you send me an oauth url

1 Like

It did not work. Here is the oauth url:
https://authorize.roblox.com/?client_id=2969482479946332042&response_type=code&redirect_uri=https%3A%2F%2Fholocafe.nwygo.com%2Fauthorize&scope=openid+profile+group%3Aread&state=abc123&code_challenge=W29iamVjdCBQcm9taXNlXQ&code_challenge_method=S256&step=permissionRequest

It is because your code challenge is [object Promise];
Add an await

var code_challenge = base64URLEncode(await sha256(code_verifier));

Console says that that line is “missing ) after argument list”. I don’t even see where there should be a parenthesis. That error stopped the rest of the code from running.
chrome_MtL7Srkld3

Please show the code for script.js

var scopes = ["openid", "profile", "group:read"]; // Replace with all the scopes

function generateRandomString(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

function base64URLEncode(str) {
    return btoa(str)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}

async function sha256(plain) {
    // Returns the SHA-256 hash of the input string
    const encoder = new TextEncoder();
    const data = encoder.encode(plain);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
    return hashHex;
  }

// Generate code verifier and challenge
var code_verifier = generateRandomString(128);
var code_challenge = ase64URLEndoce(await sha256(code_verifier));

console.log(code_challenge)

let redirectURI = encodeURIComponent("https://holocafe.nwygo.com/authorize") // Note to self: Would redirect them to /authorize?code={code} | I can then access the code using params with express or smth ig

var OAuthURL = "https://apis.roblox.com/oauth/v1/authorize" +
    "?client_id=2969482479946332042" +
    "&code_challenge=" + code_challenge +
    "&code_challenge_method=S256" +
    "&redirect_uri=" + redirectURI +
    "&scope=" + scopes.join("%20") +
    "&response_type=code" +
    "&state=abc123"

console.log("OAuthURL:", OAuthURL);

let authButton = document.getElementById('authButton')
authButton.href = OAuthURL

You misspelled base64URLEncode as ase64URLEndoce

Oh my god that’s embarrassing :flushed:

It still says the a parenthesis is missing :confused:
image
Very weird since there isn’t anywhere for a parenthesis to go…

You arent allowed to do await in top-level, my bad. Also believed I fixed that error for you

var scopes = ["openid", "profile", "group:read"]; // Replace with all the scopes

function generateRandomString(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

function base64URLEncode(str) {
    return btoa(str)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}

async function sha256(plain) {
    // Returns the SHA-256 hash of the input string
    const encoder = new TextEncoder();
    const data = encoder.encode(plain);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
    return hashHex;
  }

// Generate code verifier and challenge
async function GenerateOAuthURL(){
    var code_verifier = generateRandomString(128);
    var code_challenge = base64URLEncode(await sha256(code_verifier));

    console.log(code_challenge)

    let redirectURI = encodeURIComponent("https://holocafe.nwygo.com/authorize") // Note to self: Would redirect them to /authorize?code={code} | I can then access the code using params with express or smth ig

    var OAuthURL = "https://apis.roblox.com/oauth/v1/authorize" +
        "?client_id=2969482479946332042" +
        "&code_challenge=" + code_challenge +
        "&code_challenge_method=S256" +
        "&redirect_uri=" + redirectURI +
        "&scope=" + scopes.join("%20") +
        "&response_type=code" +
        "&state=abc123"

    console.log("OAuthURL:", OAuthURL);

    let authButton = document.getElementById('authButton')
    authButton.href = OAuthURL
}

GenerateOAuthURL()

WHOA. You fixed the error! (I just have to fix this part now in my code)

Thank you so much. I spent a long time trying to get it to work and I wish I came to the devforum sooner lol.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.