Using Auth0Lock for authentication with express + angular2 app, "UnauthorizedError: jwt malformed"
Using Auth0Lock for authentication with express + angular2 app, "UnauthorizedError: jwt malformed"
TL;DR: 登录后 JWT 保存在客户端(来自 auth0lock),当使用 angular2-jwt 发送到服务器端时,当使用 express-jwt 验证接收时:"UnauthorizedError: jwt malformed"
你好,我在做SPA,前端是angular2,后端是express,
我正在研究的当前功能是身份验证,经过一些研究我认为最好的解决方案是使用 Auth0。
我正在使用 Auth0Lock,因为我不喜欢托管页面,并退出 SPA,我遇到的问题是在登录后,我创建了一个按钮来测试身份验证是否通过我的服务器端,单击它后,我在服务器端收到 "UnauthorizedError: jwt malformed"。
我的登录流程一开始只有客户端,你点击登录按钮,你得到Auth0Lock,你登录,客户端保存一个JWT,一旦你登录,当你点击测试按钮,使用Angular2-jwt模块将JWT传递到服务器端,并在服务器端验证JWT。
客户端认证服务:
@Injectable()
export class AuthService {
private lock: any;
private userProfile: any;
constructor(public router: Router) {
this.lock = new Auth0Lock(AUTH_CONFIG.clientID, AUTH_CONFIG.domain, {
oidcConformant: true,
autoclose: true,
auth: {
redirectUrl: AUTH_CONFIG.callbackURL,
responseType: 'token id_token',
audience: AUTH_CONFIG.audience,
params: {
scope: 'openid profile user_metadata email'
}
},
rememberLastLogin: true,
allowForgotPassword: true,
languageDictionary: { title: 'Cowoffee'},
socialButtonStyle: 'small'
});
}
public login(): void {
this.lock.show();
}
// Call this method in app.component
// if using path-based routing
public handleAuthentication(): void {
this.lock.on('authenticated', (authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
this.router.navigate(['/']);
}
});
this.lock.on('authorization_error', (err) => {
this.router.navigate(['/']);
console.log(err);
alert(`Error: ${err.error}. Check the console for further details.`);
});
}
// Call this method in app.component
// if using hash-based routing
public handleAuthenticationWithHash(): void {
this
.router
.events
.filter(event => event instanceof NavigationStart)
.filter((event: NavigationStart) => (/access_token|id_token|error/).test(event.url))
.subscribe(() => {
this.lock.resumeAuth(window.location.hash, (err, authResult) => {
if (err) {
this.router.navigate(['/']);
console.log(err);
alert(`Error: ${err.error}. Check the console for further details.`);
return;
}
this.setSession(authResult);
this.router.navigate(['/']);
});
});
}
private setSession(authResult): void {
// Set the time that the access token will expire at
const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
localStorage.setItem('access_token', authResult.accessToken);
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('expires_at', expiresAt);
}
public logout(): void {
// Remove tokens and expiry time from localStorage
localStorage.removeItem('access_token');
localStorage.removeItem('id_token');
localStorage.removeItem('expires_at');
// Go back to the home route
this.router.navigate(['/']);
}
public isAuthenticated(): boolean {
// Check whether the current time is past the
// access token's expiry time
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
return new Date().getTime() < expiresAt;
}
public async getProfile(): Promise<any> {
if (this.userProfile) {
return this.userProfile;
}
const accessToken = localStorage.getItem('access_token');
if (!accessToken) {
throw new Error('Access token must exist to fetch profile');
}
const test: any = promisifyAll(this.lock);
this.userProfile = test.getUserInfoAsync(accessToken);
return this.userProfile;
}
}
客户端提供商:
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenGetter: (() => sessionStorage.getItem('access_token')),
globalHeaders: [{'Content-Type': 'application/json'}],
}), http, options);
}
服务器端验证设置:
export const JwtConfiguration = {
// Dynamically provide a signing key
// based on the kid in the header and
// the singing keys provided by the JWKS endpoint.
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://*******.eu.auth0.com/.well-known/jwks.json`
}),
// Validate the audience and the issuer.
audience: 'https://*******',
issuer: `https://*******.eu.auth0.com/`,
algorithms: ['RS256']
};
控制器内的服务器端验证:
@JsonController('/test')
export class TestController {
@Get('/')
@UndefinedResultCode(500)
@UseBefore(jwt(JwtConfiguration))
public TestJWT(): string {
return 'success';
}
}
我想说的是,大部分代码都是从 Auth0 文档中复制和使用的,非常感谢您的帮助,抱歉拖了这么久 post!
更新:
问题是令牌保存在 localStorage 中,我试图从 sessionStorage 中取回它,相当尴尬,当你只是复制粘贴示例时发生......之后一切正常。
问题是令牌保存在 localStorage 中,我试图从 sessionStorage 中检索它,相当尴尬,当您只是复制粘贴示例时发生...之后一切正常。
如果有人在用Auth0,注意new community,旧的没用,祝大家好运。 :)
TL;DR: 登录后 JWT 保存在客户端(来自 auth0lock),当使用 angular2-jwt 发送到服务器端时,当使用 express-jwt 验证接收时:"UnauthorizedError: jwt malformed"
你好,我在做SPA,前端是angular2,后端是express, 我正在研究的当前功能是身份验证,经过一些研究我认为最好的解决方案是使用 Auth0。
我正在使用 Auth0Lock,因为我不喜欢托管页面,并退出 SPA,我遇到的问题是在登录后,我创建了一个按钮来测试身份验证是否通过我的服务器端,单击它后,我在服务器端收到 "UnauthorizedError: jwt malformed"。
我的登录流程一开始只有客户端,你点击登录按钮,你得到Auth0Lock,你登录,客户端保存一个JWT,一旦你登录,当你点击测试按钮,使用Angular2-jwt模块将JWT传递到服务器端,并在服务器端验证JWT。
客户端认证服务:
@Injectable()
export class AuthService {
private lock: any;
private userProfile: any;
constructor(public router: Router) {
this.lock = new Auth0Lock(AUTH_CONFIG.clientID, AUTH_CONFIG.domain, {
oidcConformant: true,
autoclose: true,
auth: {
redirectUrl: AUTH_CONFIG.callbackURL,
responseType: 'token id_token',
audience: AUTH_CONFIG.audience,
params: {
scope: 'openid profile user_metadata email'
}
},
rememberLastLogin: true,
allowForgotPassword: true,
languageDictionary: { title: 'Cowoffee'},
socialButtonStyle: 'small'
});
}
public login(): void {
this.lock.show();
}
// Call this method in app.component
// if using path-based routing
public handleAuthentication(): void {
this.lock.on('authenticated', (authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
this.router.navigate(['/']);
}
});
this.lock.on('authorization_error', (err) => {
this.router.navigate(['/']);
console.log(err);
alert(`Error: ${err.error}. Check the console for further details.`);
});
}
// Call this method in app.component
// if using hash-based routing
public handleAuthenticationWithHash(): void {
this
.router
.events
.filter(event => event instanceof NavigationStart)
.filter((event: NavigationStart) => (/access_token|id_token|error/).test(event.url))
.subscribe(() => {
this.lock.resumeAuth(window.location.hash, (err, authResult) => {
if (err) {
this.router.navigate(['/']);
console.log(err);
alert(`Error: ${err.error}. Check the console for further details.`);
return;
}
this.setSession(authResult);
this.router.navigate(['/']);
});
});
}
private setSession(authResult): void {
// Set the time that the access token will expire at
const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
localStorage.setItem('access_token', authResult.accessToken);
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('expires_at', expiresAt);
}
public logout(): void {
// Remove tokens and expiry time from localStorage
localStorage.removeItem('access_token');
localStorage.removeItem('id_token');
localStorage.removeItem('expires_at');
// Go back to the home route
this.router.navigate(['/']);
}
public isAuthenticated(): boolean {
// Check whether the current time is past the
// access token's expiry time
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
return new Date().getTime() < expiresAt;
}
public async getProfile(): Promise<any> {
if (this.userProfile) {
return this.userProfile;
}
const accessToken = localStorage.getItem('access_token');
if (!accessToken) {
throw new Error('Access token must exist to fetch profile');
}
const test: any = promisifyAll(this.lock);
this.userProfile = test.getUserInfoAsync(accessToken);
return this.userProfile;
}
}
客户端提供商:
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenGetter: (() => sessionStorage.getItem('access_token')),
globalHeaders: [{'Content-Type': 'application/json'}],
}), http, options);
}
服务器端验证设置:
export const JwtConfiguration = {
// Dynamically provide a signing key
// based on the kid in the header and
// the singing keys provided by the JWKS endpoint.
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://*******.eu.auth0.com/.well-known/jwks.json`
}),
// Validate the audience and the issuer.
audience: 'https://*******',
issuer: `https://*******.eu.auth0.com/`,
algorithms: ['RS256']
};
控制器内的服务器端验证:
@JsonController('/test')
export class TestController {
@Get('/')
@UndefinedResultCode(500)
@UseBefore(jwt(JwtConfiguration))
public TestJWT(): string {
return 'success';
}
}
我想说的是,大部分代码都是从 Auth0 文档中复制和使用的,非常感谢您的帮助,抱歉拖了这么久 post!
更新: 问题是令牌保存在 localStorage 中,我试图从 sessionStorage 中取回它,相当尴尬,当你只是复制粘贴示例时发生......之后一切正常。
问题是令牌保存在 localStorage 中,我试图从 sessionStorage 中检索它,相当尴尬,当您只是复制粘贴示例时发生...之后一切正常。
如果有人在用Auth0,注意new community,旧的没用,祝大家好运。 :)