Implementation Examples
This section contains practical examples of OAuth 2.0 authentication flow implementation in different languages and frameworks.
C# (ASP.NET Core)
The native Fanbase language. Examples with ASP.NET Core and standard .NET libraries.
Authorization Flow with ASP.NET Core
csharp
// Program.cs or Startup.cs - Configure services
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
// Controllers/OAuthController.cs
using Microsoft.AspNetCore.Mvc;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text.Json;
public class OAuthController : Controller
{
private const string ClientId = "your_client_id";
private const string ClientSecret = "your_client_secret";
private const string RedirectUri = "https://your-domain.com.br/callback";
private const string LoginBaseUrl = "{login-producao}";
private const string SecurityBaseUrl = "{security-producao}";
[HttpGet("/login")]
public IActionResult StartLogin()
{
var state = Convert.ToBase64String(RandomNumberGenerator.GetBytes(16)).TrimEnd('=')[..16];
HttpContext.Session.SetString("oauth_state", state);
var authUrl = $"{LoginBaseUrl}/authorize?response_type=code&scope=openid%20profile" +
$"&client_id={ClientId}&redirect_uri={Uri.EscapeDataString(RedirectUri)}&state={state}";
return Redirect(authUrl);
}
[HttpGet("/callback")]
public async Task<IActionResult> Callback(string? code, string? error, string? state)
{
if (!string.IsNullOrEmpty(error))
return BadRequest($"Error: {error}");
var storedState = HttpContext.Session.GetString("oauth_state");
if (state != storedState)
return BadRequest("Invalid state");
if (string.IsNullOrEmpty(code))
return BadRequest("Code not received");
using var http = new HttpClient();
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "authorization_code",
["client_id"] = ClientId,
["client_secret"] = ClientSecret,
["code"] = code
});
var response = await http.PostAsync($"{SecurityBaseUrl}/api/token/v2", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var tokens = JsonSerializer.Deserialize<JsonElement>(json);
var idToken = tokens.GetProperty("id_token").GetString()!;
var accessToken = tokens.GetProperty("access_token").GetString()!;
// Validate id_token (use Microsoft.IdentityModel.Tokens or System.IdentityModel.Tokens.Jwt)
// var principal = ValidateIdToken(idToken, ClientId, ClientSecret);
HttpContext.Session.SetString("access_token", accessToken);
return Redirect("/dashboard");
}
[HttpGet("/userinfo")]
public async Task<IActionResult> UserInfo()
{
var accessToken = HttpContext.Session.GetString("access_token");
if (string.IsNullOrEmpty(accessToken))
return Unauthorized();
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await http.GetAsync($"{SecurityBaseUrl}/api/userinfo");
response.EnsureSuccessStatusCode();
var userInfo = await response.Content.ReadAsStringAsync();
return Content(userInfo, "application/json");
}
}Get Token with Client Credentials (C#)
csharp
using System.Net.Http.Headers;
using System.Text.Json;
public async Task<string> GetTokenClientCredentialsAsync()
{
var clientId = "your_client_id";
var clientSecret = "your_client_secret";
var securityBaseUrl = "{security-producao}";
using var http = new HttpClient();
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = clientId,
["client_secret"] = clientSecret
});
var response = await http.PostAsync($"{securityBaseUrl}/api/token", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var tokenResponse = JsonSerializer.Deserialize<JsonElement>(json);
return tokenResponse.GetProperty("access_token").GetString()!;
}ID Token Validation in C#
csharp
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
public ClaimsPrincipal ValidateIdToken(string idToken, string clientId, string clientSecret)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(clientSecret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var validationParameters = new TokenValidationParameters
{
ValidIssuer = "fanbase",
ValidAudience = clientId,
IssuerSigningKey = key,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
var handler = new JwtSecurityTokenHandler();
var principal = handler.ValidateToken(idToken, validationParameters, out _);
return principal;
}Recommended JWT Library for C#
- Microsoft.IdentityModel.Tokens + System.IdentityModel.Tokens.Jwt (standard NuGet packages)
bash
dotnet add package Microsoft.IdentityModel.Tokens
dotnet add package System.IdentityModel.Tokens.JwtJavaScript (Frontend)
Complete Example
javascript
const CLIENT_ID = 'your_client_id';
const REDIRECT_URI = 'https://your-domain.com.br/callback';
const LOGIN_BASE_URL = '{login-producao}';
const SECURITY_BASE_URL = '{security-producao}';
function generateState() {
return btoa(Math.random().toString()).substring(0, 16);
}
function startLogin() {
const state = generateState();
sessionStorage.setItem('oauth_state', state);
const authUrl = `${LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${state}`;
window.location.href = authUrl;
}
async function exchangeCodeForToken(code) {
const response = await fetch(`${SECURITY_BASE_URL}/api/token/v2`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: CLIENT_ID,
client_secret: 'your_client_secret',
code: code
})
});
if (!response.ok) {
throw new Error('Error exchanging code for tokens');
}
return await response.json();
}
function processCallback() {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const error = urlParams.get('error');
const state = urlParams.get('state');
const storedState = sessionStorage.getItem('oauth_state');
if (error) {
console.error('Authentication error:', error);
return;
}
if (state !== storedState) {
console.error('State does not match');
return;
}
if (code) {
exchangeCodeForToken(code)
.then(tokens => {
console.log('Tokens received:', tokens);
validateAndUseTokens(tokens);
})
.catch(error => {
console.error('Error:', error);
});
}
}Node.js (Backend)
Example with Express
javascript
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const CLIENT_ID = 'your_client_id';
const CLIENT_SECRET = 'your_client_secret';
const REDIRECT_URI = 'https://your-domain.com.br/callback';
const LOGIN_BASE_URL = '{login-producao}';
const SECURITY_BASE_URL = '{security-producao}';
app.get('/login', (req, res) => {
const state = require('crypto').randomBytes(16).toString('hex');
req.session.oauthState = state;
const authUrl = `${LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${state}`;
res.redirect(authUrl);
});
app.get('/callback', async (req, res) => {
const { code, error, state } = req.query;
if (error) {
return res.status(400).send(`Error: ${error}`);
}
if (state !== req.session.oauthState) {
return res.status(400).send('Invalid state');
}
try {
const tokenResponse = await fetch(`${SECURITY_BASE_URL}/api/token/v2`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: code
})
});
const tokens = await tokenResponse.json();
const decoded = jwt.verify(tokens.id_token, CLIENT_SECRET, {
issuer: 'fanbase',
audience: CLIENT_ID
});
req.session.user = decoded;
res.redirect('/dashboard');
} catch (error) {
res.status(500).send(`Error: ${error.message}`);
}
});
app.get('/userinfo', async (req, res) => {
const accessToken = req.session.tokens?.access_token;
if (!accessToken) {
return res.status(401).send('Not authenticated');
}
try {
const response = await fetch(`${SECURITY_BASE_URL}/api/userinfo`, {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const userInfo = await response.json();
res.json(userInfo);
} catch (error) {
res.status(500).send(`Error: ${error.message}`);
}
});Python
Example with Flask
python
from flask import Flask, redirect, request, session
import requests
import jwt
import secrets
app = Flask(__name__)
app.secret_key = 'your_secret_key'
CLIENT_ID = 'your_client_id'
CLIENT_SECRET = 'your_client_secret'
REDIRECT_URI = 'https://your-domain.com.br/callback'
LOGIN_BASE_URL = '{login-producao}'
SECURITY_BASE_URL = '{security-producao}'
@app.route('/login')
def login():
state = secrets.token_urlsafe(16)
session['oauth_state'] = state
auth_url = f'{LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&state={state}'
return redirect(auth_url)
@app.route('/callback')
def callback():
code = request.args.get('code')
error = request.args.get('error')
state = request.args.get('state')
if error:
return f'Error: {error}', 400
if state != session.get('oauth_state'):
return 'Invalid state', 400
token_data = {
'grant_type': 'authorization_code',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'code': code
}
response = requests.post(
f'{SECURITY_BASE_URL}/api/token/v2',
data=token_data
)
tokens = response.json()
try:
decoded = jwt.decode(
tokens['id_token'],
CLIENT_SECRET,
issuer='fanbase',
audience=CLIENT_ID,
algorithms=['HS256']
)
session['user'] = decoded
session['tokens'] = tokens
return redirect('/dashboard')
except jwt.InvalidTokenError as e:
return f'Invalid token: {e}', 400
@app.route('/userinfo')
def userinfo():
access_token = session.get('tokens', {}).get('access_token')
if not access_token:
return 'Not authenticated', 401
headers = {'Authorization': f'Bearer {access_token}'}
response = requests.get(f'{SECURITY_BASE_URL}/api/userinfo', headers=headers)
return response.json()PHP
Basic Example
php
<?php
session_start();
define('CLIENT_ID', 'your_client_id');
define('CLIENT_SECRET', 'your_client_secret');
define('REDIRECT_URI', 'https://your-domain.com.br/callback');
define('LOGIN_BASE_URL', '{login-producao}');
define('SECURITY_BASE_URL', '{security-producao}');
function startLogin() {
$state = bin2hex(random_bytes(16));
$_SESSION['oauth_state'] = $state;
$authUrl = LOGIN_BASE_URL . '/authorize?' . http_build_query([
'response_type' => 'code',
'scope' => 'openid profile',
'client_id' => CLIENT_ID,
'redirect_uri' => REDIRECT_URI,
'state' => $state
]);
header('Location: ' . $authUrl);
exit;
}
function processCallback() {
$code = $_GET['code'] ?? null;
$error = $_GET['error'] ?? null;
$state = $_GET['state'] ?? null;
if ($error) {
die('Error: ' . $error);
}
if ($state !== $_SESSION['oauth_state']) {
die('Invalid state');
}
$ch = curl_init(SECURITY_BASE_URL . '/api/token/v2');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'grant_type' => 'authorization_code',
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'code' => $code
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$tokens = json_decode($response, true);
$_SESSION['tokens'] = $tokens;
return $tokens;
}
function getUserInfo($accessToken) {
$ch = curl_init(SECURITY_BASE_URL . '/api/userinfo');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $accessToken
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
return json_decode($response, true);
}
?>Get Token with Client Credentials (For Connect Integrations)
See C# example in the C# section above.
JavaScript
javascript
async function getTokenClientCredentials() {
const CLIENT_ID = 'your_client_id';
const CLIENT_SECRET = 'your_client_secret';
const SECURITY_BASE_URL = '{security-producao}';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
});
const response = await fetch(`${SECURITY_BASE_URL}/api/token?${params}`, {
method: 'POST'
});
if (!response.ok) {
throw new Error('Error getting token');
}
const data = await response.json();
return data.access_token;
}Node.js
javascript
async function getTokenConnect() {
const CLIENT_ID = 'your_client_id';
const CLIENT_SECRET = 'your_client_secret';
const SECURITY_BASE_URL = '{security-producao}';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
});
const response = await fetch(`${SECURITY_BASE_URL}/api/token?${params}`, {
method: 'POST'
});
const data = await response.json();
return data.access_token;
}Using Connect API
Example: Create Object in Queue (C#)
csharp
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
public async Task<JsonElement> CreateQueueObjectAsync(string accessToken)
{
var connectBaseUrl = "{connect-producao}";
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("AccessToken", accessToken);
var body = JsonSerializer.Serialize(new
{
action = "ticket-create",
data = new
{
ticket_data = "value",
buyer_data = "value"
}
});
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await http.PostAsync($"{connectBaseUrl}/api/v1/integration/queue", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<JsonElement>(json);
}Example: Create Object in Queue (JavaScript)
javascript
async function createQueueObject(accessToken) {
const CONNECT_BASE_URL = '{connect-producao}';
const response = await fetch(`${CONNECT_BASE_URL}/api/v1/integration/queue`, {
method: 'POST',
headers: {
'AccessToken': accessToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'ticket-create',
data: {
ticket_data: 'value',
buyer_data: 'value'
}
})
});
if (!response.ok) {
throw new Error('Error creating object in queue');
}
return await response.json();
}Example: Get Complete Profile (C#)
csharp
using System.Net.Http.Headers;
using System.Text.Json;
public async Task<JsonElement> GetProfileAsync(string clientId, string jwtToken)
{
var securityBaseUrl = "{security-producao}";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
var response = await http.GetAsync($"{securityBaseUrl}/api/profile/{clientId}");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<JsonElement>(json);
var code = result.GetProperty("header").GetProperty("codigo").GetInt32();
if (code != 1)
throw new InvalidOperationException(result.GetProperty("header").GetProperty("msg").GetString());
return result.GetProperty("data");
}Example: Get Complete Profile (JavaScript)
javascript
async function getProfile(clientId, jwtToken) {
const SECURITY_BASE_URL = '{security-producao}';
const response = await fetch(`${SECURITY_BASE_URL}/api/profile/${clientId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${jwtToken}`
}
});
if (!response.ok) {
throw new Error('Error getting profile');
}
const result = await response.json();
if (result.header.codigo !== 1) {
throw new Error(result.header.msg);
}
return result.data;
}