JWT 为啥我可以绕过身份验证?

Posted

技术标签:

【中文标题】JWT 为啥我可以绕过身份验证?【英文标题】:JWT why can I bypass authentication?JWT 为什么我可以绕过身份验证? 【发布时间】:2018-05-12 08:43:03 【问题描述】:

我正在关注 this auth0 的 react/express + jwt 网页教程。

一切似乎都很好。登录/注销,访问安全页面都很好。

除了我可以用假令牌绕过登录。如果我只是去 jwt.io 并生成一个尚未过期的令牌,我可以在没有实际登录的情况下访问安全页面。我在这里错过了什么?

这是处理身份验证的代码部分:

./utils/AuthService.js
const ID_TOKEN_KEY = 'id_token';
const ACCESS_TOKEN_KEY = 'access_token';

const CLIENT_ID = 'auht0 client id';
const CLIENT_DOMAIN = 'foo.eu.auth0.com';
const REDIRECT = 'http://localhost:3000/callback';
const SCOPE = 'openid profile ';
const AUDIENCE = 'https://foo.eu.auth0.com/api/v2/';

var auth = new auth0.WebAuth(
  clientID: CLIENT_ID,
  domain: CLIENT_DOMAIN
);

export function login() 
  auth.authorize(
    responseType: 'token id_token',
    redirectUri: REDIRECT,
    audience: AUDIENCE,
    scope: SCOPE
  );


export function logout() 
  clearIdToken();
  clearAccessToken();
  browserHistory.push('/');


export function requireAuth(nextState, replace) 
  if (!isLoggedIn()) 
    replace(pathname: '/');
  


export function getIdToken() 
  return localStorage.getItem(ID_TOKEN_KEY);


export function getAccessToken() 
  return localStorage.getItem(ACCESS_TOKEN_KEY);


function clearIdToken() 
  localStorage.removeItem(ID_TOKEN_KEY);


function clearAccessToken() 
  localStorage.removeItem(ACCESS_TOKEN_KEY);


// Helper function that will allow us to extract the access_token and id_token
function getParameterByName(name) 
  let match = RegExp('[#&]' + name + '=([^&]*)').exec(window.location.hash);
  return match && decodeURIComponent(match[1].replace(/\+/g, ' '));


// Get and store access_token in local storage
export function setAccessToken() 
  let accessToken = getParameterByName('access_token');
  localStorage.setItem(ACCESS_TOKEN_KEY, accessToken);


// Get and store id_token in local storage
export function setIdToken() 
  let idToken = getParameterByName('id_token');
  localStorage.setItem(ID_TOKEN_KEY, idToken);


export function isLoggedIn() 
  const idToken = getIdToken();
  return !!idToken && !isTokenExpired(idToken);


function getTokenExpirationDate(encodedToken) 
  const token = decode(encodedToken);
  if (!token.exp)  return null; 

  const date = new Date(0);
  date.setUTCSeconds(token.exp);

  return date;


function isTokenExpired(token) 
  const expirationDate = getTokenExpirationDate(token);
  return expirationDate < new Date();

【问题讨论】:

【参考方案1】:

您发布的部分只是从本地存储中存储/检索令牌。 身份验证本身在服务器端处理

  secret: jwks.expressJwtSecret(
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        // YOUR-AUTH0-DOMAIN name e.g prosper.auth0.com
        jwksUri: "https://YOUR-AUTH0-DOMAIN/.well-known/jwks.json"
    ),
    // This is the identifier we set when we created the API
    audience: 'YOUR-API-AUDIENCE-ATTRIBUTE',
    issuer: 'YOUR-AUTH0-DOMAIN',
    algorithms: ['RS256']
);

服务器端功能必须检查 JWT 令牌签名。如果没有私钥,您将无法生成 JWT 令牌的有效签名。

如果真的可以绕过认证,说明服务器存在严重的安全问题(签名没有正确验证)。也许对于测试/演示服务,它没有实现。

【讨论】:

因此不会从服务器检索任何信息,但仍可访问 react/front-end 安全页面,并且显示任何不是由服务器发送的内容... 令牌仅用于访问后端服务,并可选择向客户端提供基本用户信息(声明)。客户端应用程序可以访问,但它不应该能够从后端检索/显示/任何用户(业务)内容,除非用户通过后端服务进行身份验证。

以上是关于JWT 为啥我可以绕过身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

为啥验证函数中的令牌参数在 jwt 身份验证中显示错误?

我们如何在同一spring应用程序中同时添加JWT和基本身份验证?

为啥我的 JWT 不记名身份验证在令牌说 5 分钟后将令牌识别为过期?

如何绕过特定域的经过身份验证的端点上的弹簧安全性?

我们如何在同一个 Spring 应用程序中同时添加 JWT 和基本身份验证? [关闭]

应用离线时如何绕过 Firebase 身份验证?