JWT 为什么我可以绕过认证?
JWT why can I bypass authentication?
我正在关注一个 react/express + jwt 网页的 this auth0 教程。
一切似乎都很好。 Login/logout,访问安全页面一切正常。
除非我可以使用假令牌绕过登录。如果我只是去 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();
}
您发布的部分只是从本地存储中存储/检索令牌。
身份验证本身在服务器端处理
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 令牌的有效签名。
如果真的可以绕过认证,说明服务器存在严重的安全问题(签名未正确验证)。也许对于 test/demo 服务,它没有实现。
我正在关注一个 react/express + jwt 网页的 this auth0 教程。
一切似乎都很好。 Login/logout,访问安全页面一切正常。
除非我可以使用假令牌绕过登录。如果我只是去 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();
}
您发布的部分只是从本地存储中存储/检索令牌。 身份验证本身在服务器端处理
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 令牌的有效签名。
如果真的可以绕过认证,说明服务器存在严重的安全问题(签名未正确验证)。也许对于 test/demo 服务,它没有实现。