Roblox OAuth Client

About

Since Roblox has not officially created an OAuth Login system for Developers to use, my company decided to publicly release ours which uses RAMPAGE ID. Users simply create a RAMPAGE Account & Link platforms such as Discord, Roblox, and more to their account.

RAMPAGE ID provides a simple PHP example for developers to easily integrate Roblox Sign-on easily. Sign in with Roblox allows developers to get the following & ensure return data is valid:

{"success":true,"roblox_username":"Roblox","roblox_id":1,"roblox_avatar_url":"roblox.com/avatar.png"}

How it works

howitworks

A more in-depth article, tutorial, and API information are on rampage place.

Screenshots

image
image

Get Started

No API keys are required, simply add a few lines of PHP! Full documentation and download Tutorial & Download here

So Simple!

It’s so simple it’s only about 15 lines of code! We do all the hard work in the backend. Only 4 lines to build the URL!

Once you build the URL you simply redirect the user to it!

Not much more lines of code to start the session & handle data. Few lines of code to handle backend to request access to data with access key & simple session system with logout.

Project Samples

PHP & ExpressJS Example, more to come.

Verify

In-order to use login with Roblox must have RAMPAGE ID account & roblox account linked.

Link your account at: (requires rampage id)
https://id.rampage.place/link

Create RAMPAGE ID at:

RAMPAGE Interactive’s OAuth & RAMPAGE ID is not endorsed, sponsored, or affiliated by Roblox Corporation. Please report any and all bugs relating to this product to us. This post may be outdated with current API changes for RAMPAGE, Please go to RAMPAGE’s website for updated documentation posted by my engineers.

12 Likes

Demo

Demo: https://demo.vq9o.com/oauth
Buttons: https://demo.vq9o.com/oauth/buttons.html

Session Example

Took me only 15 minutes to put this together, for example, Login/Logout is built with our OAuth.

<?php
session_start();
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

function generate()
{
    return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}

// Format URL
$scopes = array("target_roblox", "roblox_username", "roblox_display", "roblox_id", "roblox_avatar_url"); // Add scopes you want here.
$return = "https://demo.vq9o.com/oauth/index.php"; // Return here.

// Format the URL (Do not touch)
$scopes = implode(',', $scopes); // Format to comma-seperated-value
$url = "https://id.rampagestudios.org/login/sso?scopes=" . rawurlencode($scopes) . "&return_url=" . rawurlencode($return);

// Handle URL
if (!empty($_GET["logout"])) {
    echo "<b>Logged out!</b>";
    setcookie(session_name(), '', 100);
    session_unset();
    session_destroy();
    $_SESSION = array();
}

function GET($url, $fields)
{
    $ch = curl_init($url);
    $payload = json_encode($fields);

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $result = curl_exec($ch);
    return json_decode($result);
    curl_close($ch);
}

if (!empty($_GET["target_roblox_key"])) {
    $GeneratedCheckURL = "https://api.rampagestudios.org/v1/oauth/request/index.php";
    $Fields = [
        "key" => htmlspecialchars($_GET["target_roblox_key"]),
        "platform" => "target_roblox"
    ];
    $data = GET($GeneratedCheckURL, $Fields);

    if ($data->success == true) {
        $_SESSION["rampage_oauth_session"] = $data;
        echo "<b>Authorized!</b>";
        echo "<p>JSON:</p>". json_encode($data);
    } else {
        echo "<b>Login authorization key is expired!</b>";
    }
} else {
    if (!empty($_GET["failed"])) {
        if (htmlspecialchars($_GET["failed"]) == true) {
            echo "<b>Login failed due to: Pending Verification, No Account Found, No Roblox Account, or another error.</b>";
        }
    }
}
?>

<html>
<link rel="stylesheet" href="https://rampage.host/bulma.css">
<link rel="stylesheet" href="https://demo.vq9o.com/oauth/style.css">
<link rel="stylesheet" type="text/css" href="https://rampage.host/bulma_tooltip.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&amp;display=swap">

<nav class="navbar is-white topNav">
    <div class="container">
        <div class="navbar-brand">
            <a class="navbar-item">
                <p>Roblox <b>OAuth</b></p>
            </a>
        </div>
        <div class=" navbar-end">
            <div class="navbar-item">
                <?php
                    if (empty($_SESSION["rampage_oauth_session"])) {
                        echo '<a class="button is-light" href="'. $url .'"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Login</a>';
                    } else {
                        echo '<a class="button is-dark is-outlined" href="'. $return .'?logout=true"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Logout</a>';
                        echo '<p class="image is-32x32 has-tooltip-bottom" data-tooltip="'. $_SESSION["rampage_oauth_session"]->roblox_username . '">
                        <img src="'.$_SESSION["rampage_oauth_session"]->roblox_avatar_url. '">
                    </p>';
                    }
                    ?>
            </div>
        </div>
    </div>
</nav>

</html>
?>

<html>
<link rel="stylesheet" href="https://rampage.host/bulma.css">
<link rel="stylesheet" href="https://demo.vq9o.com/oauth/style.css">
<link rel="stylesheet" type="text/css" href="https://rampage.host/bulma_tooltip.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&amp;display=swap">

<nav class="navbar is-white topNav">
    <div class="container">
        <div class="navbar-brand">
            <a class="navbar-item">
                <p>Roblox <b>OAuth</b></p>
            </a>
        </div>
        <div class=" navbar-end">
            <div class="navbar-item">
                <?php
                    if (empty($_SESSION["rampage_oauth_session"])) {
                        echo '<a class="button is-light" href="'. $url .'"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Login</a>';
                    } else {
                        echo '<a class="button is-dark is-outlined" href="'. $return .'?logout=true"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Logout</a>';
                        echo '<p class="image is-32x32 has-tooltip-bottom" data-tooltip="'. $_SESSION["rampage_oauth_session"]->username . '">
                        <img src="'.$_SESSION["rampage_oauth_session"]->avatar_url. '">
                    </p>';
                    }
                    ?>
            </div>
        </div>
    </div>
</nav>

</html>

Buttons

Tailwind CSS

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&amp;display=swap">
<link rel="stylesheet" href="https://id.rampagestudios.org/css/tailwind/tailwind.min.css">

<a href="<?php echo $url; ?>" class="flex items-center justify-center mb-6 py-4 px-6 hover:text-white leading-6 text-lg font-extrabold bg-white
    hover:bg-indigo-800 border-3 border-indigo-900 shadow rounded transition duration-200">

    <img class="w-6 h-6 mr-3" src="https://rampage.host/roblox.png" alt=""><span>Sign in with Roblox</span>
</a>

Screenshot

image
Style docs: Border Radius - Tailwind CSS

Bulma CSS

<link rel="stylesheet" href="https://rampage.host/bulma.css">
<link rel="stylesheet" href="https://demo.vq9o.com/oauth/style.css">
<link rel="stylesheet" type="text/css" href="https://rampage.host/bulma_tooltip.css">

<div class="buttons">
    <a href="<?php echo $url ?>" class="button is-medium is-outlined"><img height="25" width="25"
            src="https://rampage.host/roblox.png" alt=""><span>Sign in with Roblox</span></a><br>
    <a href="<?php echo $url ?>" class="button is-medium is-rounded is-secondary"><img height="25" width="25"
            src="https://rampage.host/roblox.png" alt=""><span>Sign
            in with Roblox</span></a>
</div>

Screenshot

image
Style docs: Button | Bulma: Free, open source, and modern CSS framework based on Flexbox

Bootstrap CSS

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css">

<div>
    <a type=" button" class="badge badge-pill badge-primary"><span><img height="25" width="25"
                src="https://rampage.host/roblox.png" alt=""><span>Sign
                in with Roblox</span></span></a>
    <a type="button" class="btn btn-outline-primary"><img height="25" width="25" src="https://rampage.host/roblox.png"
            alt=""><span>Sign
            in with Roblox</span></a>
</div>

Screenshot

image

Style docs: Buttons · Bootstrap

1 Like

Added ability to delete linked account at Roblox OAuth - RAMPAGE Group

Major API Changes

Check URL is now https://api.rampagestudios.org/v1/oauth/request/index.php

New Scopes

Roblox Scopes

  • roblox_username
    Roblox username
  • roblox_display
    Roblox display name
  • roblox_id
    Roblox user id
  • roblox_avatar_url
    Roblox avatar (URL)
  • roblox_description
    Roblox description
  • roblox_banstatus
    Roblox Ban Status (boolean)

RAMPAGE Scopes

  • rampage_id
    RAMPAGE User ID
  • rampage_email
    RAMPAGE Email

Target Scopes

  • target_roblox
    Must add this if you need roblox scopes (roblox_id, roblox_ username, etc)
  • target_rampage
    Must add this if you need rampage scopes (rampage_id, rampage_email, etc)

If the target scopes are NOT added, you can’t interact with oAuth server to get the data.

New PHP Example

<?php
session_start();
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

function generate()
{
    return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}

// Format URL
$scopes = array("target_roblox", "roblox_username", "roblox_display", "roblox_id", "roblox_avatar_url"); // Add scopes you want here.
$return = "https://demo.vq9o.com/oauth/index.php"; // Return here.

// Format the URL (Do not touch)
$scopes = implode(',', $scopes); // Format to comma-seperated-value
$url = "https://id.rampagestudios.org/login/sso?scopes=" . rawurlencode($scopes) . "&return_url=" . rawurlencode($return);

// Handle URL
if (!empty($_GET["logout"])) {
    echo "<b>Logged out!</b>";
    setcookie(session_name(), '', 100);
    session_unset();
    session_destroy();
    $_SESSION = array();
}

function GET($url, $fields)
{
    $ch = curl_init($url);
    $payload = json_encode($fields);

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $result = curl_exec($ch);
    return json_decode($result);
    curl_close($ch);
}

if (!empty($_GET["target_roblox_key"])) {
    $GeneratedCheckURL = "https://api.rampagestudios.org/v1/oauth/request/index.php";
    $Fields = [
        "key" => htmlspecialchars($_GET["target_roblox_key"]),
        "platform" => "target_roblox"
    ];
    $data = GET($GeneratedCheckURL, $Fields);

    if ($data->success == true) {
        $_SESSION["rampage_oauth_session"] = $data;
        echo "<b>Authorized!</b>";
        echo "<p>JSON:</p>". json_encode($data);
    } else {
        echo "<b>Login authorization key is expired!</b>";
    }
} else {
    if (!empty($_GET["failed"])) {
        if (htmlspecialchars($_GET["failed"]) == true) {
            echo "<b>Login failed due to: Pending Verification, No Account Found, No Roblox Account, or another error.</b>";
        }
    }
}
?>

<html>
<link rel="stylesheet" href="https://rampage.host/bulma.css">
<link rel="stylesheet" href="https://demo.vq9o.com/oauth/style.css">
<link rel="stylesheet" type="text/css" href="https://rampage.host/bulma_tooltip.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&amp;display=swap">

<nav class="navbar is-white topNav">
    <div class="container">
        <div class="navbar-brand">
            <a class="navbar-item">
                <p>Roblox <b>OAuth</b></p>
            </a>
        </div>
        <div class=" navbar-end">
            <div class="navbar-item">
                <?php
                    if (empty($_SESSION["rampage_oauth_session"])) {
                        echo '<a class="button is-light" href="'. $url .'"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Login</a>';
                    } else {
                        echo '<a class="button is-dark is-outlined" href="'. $return .'?logout=true"><img height="25" width="25"
                        src="https://rampage.host/roblox.png" alt="">&nbsp;Logout</a>';
                        echo '<p class="image is-32x32 has-tooltip-bottom" data-tooltip="'. $_SESSION["rampage_oauth_session"]->roblox_username . '">
                        <img src="'.$_SESSION["rampage_oauth_session"]->roblox_avatar_url. '">
                    </p>';
                    }
                    ?>
            </div>
        </div>
    </div>
</nav>

</html>

New Javascript Example

const express = require("express");
const http = require('node-fetch');
const cookieSession = require('cookie-session')
const app = express();

const scopes = ["target_roblox", "roblox_username", "roblox_display", "roblox_id", "roblox_avatar_url"];

app.use(cookieSession({
    name: 'rampage_oauth_session',
    keys: ["securekey123"],
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
}));

app.get("/", (req, res) => {
    if (!req.session.rampage_oauth_session.loggedin) return res.redirect(`http://localhost:${PORT}/login`);
    res.redirect(`http://localhost:${PORT}/dashboard`);
});

app.get("/dashboard", (req, res) => {
    if (!req.session.rampage_oauth_session.loggedin) return res.redirect(`http://localhost:${PORT}/login`);
    res.send(req.session.rampage_oauth_session.data)
});

app.get("/logout", (req, res) => {
    if (!req.session.rampage_oauth_session.loggedin) return res.redirect(`http://localhost:${PORT}/login`);
    req.session = null;
    res.send("Logged out!")
});

app.get("/authorize", (req, res) => {
    const target_roblox_key = req.query.target_roblox_key;

    if (!target_roblox_key) return console.log("No key found");

    const response = await fetch('https://api.rampagestudios.org/v1/oauth/request/index.php', {
        body: {
            key: target_roblox_key,
            platform: "roblox"
        }
    });
    const data = await response.json();

    if (!data.success) return console.log("Failed to verify success");
    req.session.rampage_oauth_session.loggedin = true
    req.session.rampage_oauth_session.data = data
    res.redirect(`http://localhost:${PORT}/dashboard`);
});

app.get("/login", (req, res) => {
    const scopesFormated = scopes.join(",");
    const returnURL = `localhost:${PORT}/authorize`;
    const redirect = `https://id.rampagestudios.org/login/sso?scopes=${encodeURIComponent(scopesFormated)}&return_url=${encodeURIComponent(returnURL)}`;
    res.redirect(redirect);
});


const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}.`);
});

More info at RAMPAGE OAuth - Community Tutorials - RAMPAGE.place

5/23/2022 9:40 AM PDT Update

Updated the API to properly redirect you to login to login to RAMPAGE ID if you’re detected logged out.

Avatars broken

We will push out an update later to fix avatars not showing properly.

Avatars will be fixed in a few hours.

If by ‘Roblox description’ you mean the user’s about me, this is publically available information and as a result, the application can recieve this information. On top of this, your termination status is also public information. (Is this what you mean by ban status) Just thought I’d point this out as it may trick users into thinking this data is safe. It seems you are just using the ‘scopes’ to show the correct list elements as checked, it would be better to just assume that the application knows how to use the users api and mark all of them as checked.

Mind sharing some light on how this is being done, for example, are you using an endpoint on the client, some Roblox game, etc. because at least personally I wouldn’t leave my application’s security all to some endpoint that I have no clue how it works.

1 Like

Roblox is already making OAuth, I believe it’s in closed beta atm, but good work.

Users link their account to their rampage id by placing a generated code into their description. Once they are linked they can log into websites using this resource.

Checkmarks/X’s indicate what data we are returning back to the website once you authorize it for a little transparency.

What happens when you press authorize is the server generates a temporary key which expires in 2 minutes, the user is returned back to the website with a success or failed boolean in the query with the key if it was successful.

The server then checks if the key is valid and requests to view the authorized data through a API endpoint https://api.rampagestudios.org/v1/oauth/request/index.php

https://id.rampagestudios.org/link/roblox/

Users can unlink their account from RAMPAGE ID here:
https://id.rampagestudios.org/unlink/roblox/

I created this project a while back before Roblox started development on it and decided to make it openly useable.

Avatars Fixed

Avatars are now fixed.

New Scopes

roblox_username_history
Returns array of username history. Limit of 100.

[{
      "name": "vq9o"
    },
    {
      "name": "DrxpLoxs"
    },
    {
      "name": "TimeStokes"
    },
]

roblox_groups Returns an array of groups the user has membership in. Example JSON from UserID 1. This scope is helpful for group verification if a user owns a group.

[{
        "group": {
            "id": 7384468,
            "name": "Roblox Arena Events",
            "description": "",
            "owner": {
                "buildersClubMembershipType": "None",
                "hasVerifiedBadge": false,
                "userId": 1861517257,
                "username": "RobloxArenaEvents",
                "displayName": "RobloxArenaEvents"
            },
            "shout": null,
            "memberCount": 974,
            "isBuildersClubOnly": false,
            "publicEntryAllowed": false,
            "hasVerifiedBadge": false
        },
        "role": {
            "id": 46417776,
            "name": "Member",
            "rank": 1
        }
    }, {
        "group": {
            "id": 7,
            "name": "Roblox",
            "description": "Official fan club of Roblox!",
            "owner": {
                "buildersClubMembershipType": "None",
                "hasVerifiedBadge": false,
                "userId": 1,
                "username": "Roblox",
                "displayName": "Roblox"
            },
            "shout": null,
            "memberCount": 7763992,
            "isBuildersClubOnly": false,
            "publicEntryAllowed": true,
            "hasVerifiedBadge": false
        },
        "role": {
            "id": 52,
            "name": "Owner",
            "rank": 255
        }
    }, {
        "group": {
            "id": 127081,
            "name": "Roblox Wiki",
            "description": "Roblox Wiki: http://wiki.roblox.com/ =================================\nThe official Roblox Wiki group. The purpose of this group is: 1) Normal users to give the wiki staff ideas and suggestions. 2) The wiki staff to collaborate in a more organized and efficient manner. Wiki applications are always open. The application can be found here: http://polls.roblox.com/roblox-wiki-writer-application\nPlease join if you are a wiki supporter and would like to share your ideas to the people actually who write the wiki.",
            "owner": {
                "buildersClubMembershipType": "None",
                "hasVerifiedBadge": false,
                "userId": 6783205,
                "username": "UristMcSparks",
                "displayName": "UristMcSparks"
            },
            "shout": null,
            "memberCount": 1561407,
            "isBuildersClubOnly": false,
            "publicEntryAllowed": true,
            "hasVerifiedBadge": false
        },
        "role": {
            "id": 676373,
            "name": "Wiki System Operator",
            "rank": 254
        }
    }]

We added some additional warning screens instead of redirecting back for unlinked users they will be forced to verify.

Additional updates have been added as requested by the Lead developer of RBX.Group.

You can now add a custom log to replace the RAMPAGE Logo on the authorized form. Simply add customimg=url. We also embedded the login & register form into the oAuth.

You can also get linked Discord Ids, tags, avatars, etc.



https://en.help.roblox.com/attachments/token/qaPUhVfiTubq3IOSOtofMJ72U/?name=SlsvYD7WV0.png

Discord Scopes:
target_discord
discord_id
discord_tag
discord_email
discord_avatar

target_rampage + rampage_id is required for Discord.

to-be-added:
discord_force_join + additional query join_guild_id=123.
discord_guilds to get list of guilds.

Instead of being force linked your account to another page its don’t within the same page for easier usage for players.

It seems like this is getting quite a bit cluttered with the extra scopes, any chance we could see these starting to become part of dropdowns of different types, for example ‘Roblox’, ‘RAMPAGE’ and ‘Discord’.

Service Down

RAMPAGE services will be indefinitely down until DDoS Attack has ended, we are working on bringing the servers back online.

RAMPAGE Forum is still online, as it’s on a separate Dedicated Server & IP.

https://authorize.roblox.com


they made their own.

1 Like

It’s currently not public, I started this project a while back before Roblox started on it.

Service Online

DDoS attacks have stopped, and Cloudflare under attack has been activated.

oAuth is now working.

We changed our IP Addresses for our DNS and proxy through Cloudflare now. DDoS attacks have stopped.