mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-29 12:50:59 +00:00
fix(oidc): session token vs gui token issues
This commit is contained in:
@@ -20,6 +20,7 @@ const APIError = require('../api/APIError');
|
||||
const config = require('../config');
|
||||
const { LegacyTokenError } = require('../services/auth/AuthService');
|
||||
const { Context } = require('../util/context');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
// The "/whoami" endpoint is a special case where we want to allow
|
||||
// a legacy token to be used for authentication. The "/whoami"
|
||||
@@ -47,7 +48,7 @@ const configurable_auth = options => async (req, res, next) => {
|
||||
const optional = options?.optional;
|
||||
|
||||
// Request might already have been authed (PreAuthService)
|
||||
if ( req.actor ) next();
|
||||
if ( req.actor ) return next();
|
||||
|
||||
// === Getting the Token ===
|
||||
// This step came from jwt_auth in src/helpers.js
|
||||
@@ -55,15 +56,18 @@ const configurable_auth = options => async (req, res, next) => {
|
||||
// auth middleware, it makes more sense to put it here.
|
||||
|
||||
let token;
|
||||
let tokenSource;
|
||||
// Auth token in body
|
||||
if ( req.body && req.body.auth_token )
|
||||
{
|
||||
token = req.body.auth_token;
|
||||
tokenSource = 'body';
|
||||
}
|
||||
// HTTML Auth header
|
||||
else if ( req.header && req.header('Authorization') && !req.header('Authorization').startsWith('Basic ') && req.header('Authorization') !== 'Bearer' ) { // Bearer with no space is something office does
|
||||
token = req.header('Authorization');
|
||||
token = token.replace('Bearer ', '').trim();
|
||||
tokenSource = 'header';
|
||||
if ( token === 'undefined' ) {
|
||||
APIError.create('unexpected_undefined', null, {
|
||||
msg: 'The Authorization token cannot be the string "undefined"',
|
||||
@@ -74,16 +78,19 @@ const configurable_auth = options => async (req, res, next) => {
|
||||
else if ( req.cookies && req.cookies[config.cookie_name] )
|
||||
{
|
||||
token = req.cookies[config.cookie_name];
|
||||
tokenSource = 'cookie';
|
||||
}
|
||||
// Auth token in URL
|
||||
else if ( req.query && req.query.auth_token )
|
||||
{
|
||||
token = req.query.auth_token;
|
||||
tokenSource = 'query';
|
||||
}
|
||||
// Socket
|
||||
else if ( req.handshake && req.handshake.query && req.handshake.query.auth_token )
|
||||
{
|
||||
token = req.handshake.query.auth_token;
|
||||
tokenSource = 'socket';
|
||||
}
|
||||
|
||||
if ( !token || token.startsWith('Basic ') ) {
|
||||
@@ -110,6 +117,20 @@ const configurable_auth = options => async (req, res, next) => {
|
||||
const services = context.get('services');
|
||||
const svc_auth = services.get('auth');
|
||||
|
||||
// Debug: log token source and decoded type before creating Actor (for session_required / hasHttpPowers debugging)
|
||||
if ( process.env.DEBUG ) {
|
||||
let decodedForLog;
|
||||
try {
|
||||
decodedForLog = jwt.decode(token);
|
||||
} catch ( _ ) { /* ignore */ }
|
||||
console.log('decodedForLog?', decodedForLog);
|
||||
const tokenType = decodedForLog && decodedForLog.t != null ? decodedForLog.t : '(no type or invalid jwt)';
|
||||
const tokenPreview = typeof token === 'string' && token.length > 20
|
||||
? `${token.slice(0, 12)}...${token.slice(-8)}`
|
||||
: '(short)';
|
||||
console.log(`[configurable_auth] token used for Actor: [${req.url}] source=${tokenSource}, decoded.type=${tokenType}, preview=${tokenPreview}`);
|
||||
}
|
||||
|
||||
let actor;
|
||||
try {
|
||||
actor = await svc_auth.authenticate_from_token(token);
|
||||
|
||||
@@ -152,10 +152,11 @@ const TabSecurity = {
|
||||
const password_confirm_promise = new TeePromise();
|
||||
const try_password = async () => {
|
||||
const value = $win.find('.password-entry').val();
|
||||
// Do not send Authorization: user-protected endpoints use session cookie (hasHttpPowers)
|
||||
const resp = await fetch(`${window.api_origin}/user-protected/disable-2fa`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
Authorization: `Bearer ${puter.authToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -86,10 +86,11 @@ export default {
|
||||
const password_confirm_promise = new TeePromise();
|
||||
const try_password = async () => {
|
||||
const value = password_entry.get('value');
|
||||
// No Authorization header: user-protected endpoints use session cookie (hasHttpPowers)
|
||||
const resp = await fetch(`${window.api_origin}/user-protected/disable-2fa`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
Authorization: `Bearer ${puter.authToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -114,13 +114,12 @@ async function UIWindowChangePassword (options) {
|
||||
|
||||
$(el_window).find('.form-error-msg').hide();
|
||||
|
||||
// Do not send Authorization: user-protected endpoints use session cookie (hasHttpPowers)
|
||||
$.ajax({
|
||||
url: `${window.api_origin }/user-protected/change-password`,
|
||||
type: 'POST',
|
||||
async: true,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${window.auth_token}`,
|
||||
},
|
||||
xhrFields: { withCredentials: true },
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
password: current_password,
|
||||
|
||||
@@ -182,12 +182,12 @@ async function UIWindowChangeUsername (options) {
|
||||
const new_username = $(el_window).find('.new-username').val();
|
||||
const body = { new_username };
|
||||
if ( password !== undefined && password !== '' ) body.password = password;
|
||||
// Do not send Authorization: user-protected endpoints use session cookie (hasHttpPowers)
|
||||
return fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(window.auth_token ? { 'Authorization': `Bearer ${window.auth_token}` } : {}),
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user