express -jwt и Angular 9 с поваром ie: токен не установлен в заголовке `Authorization` - PullRequest
0 голосов
/ 15 апреля 2020

Хорошо, привет,

Я работаю над реализацией JWT между моим express бэкэндом и Angular 9.

Я решил go с поваром ie (который я получу позже).

Используя express -jwt, я могу создать повара ie и отправить его на мой angular приложение со следующим кодом:

// The middleware function
const checkIfAuthenticated = expressJwt({
   secret: RSA_PUBLIC_KEY
})

[...]

// The part where I send the cookie to Angular
res.status(200)
   .cookie('SESSIONID', jwtBearerToken, {httpOnly:true, secure:false})
   .send('OK');

[...]

// My testing route, to be tried after the browser got the cookie
app.get('/test', checkIfAuthenticated, (req, res) => {
    console.log(req.cookies)
    res.status(200).json("Authorized!")
})

Я могу видеть повара ie, используя инструменты разработчиков (обратите внимание на secure:false во время разработки), но если я позволю checkIfAuthenticated активирован Я получу следующее сообщение:

UnauthorizedError: No authorization token was found

Затем запросы, сделанные Angular, содержат токен, , но не в заголовке авторизации, как описано в учебниках (Например: https://blog.angular-university.io/angular-jwt-authentication/) , вместо этого токен находится у обычного повара ie.

Это удивительно, поскольку в отношении express -jwt документации:

Поведение модуля по умолчанию заключается в извлечении JWT из заголовка Authorization

. С помощью Wireshark я наблюдал, пока звонил g бэкэнд, токен JWT передается как обычный повар ie, где express -jwt ожидает найти его в заголовке авторизации.

Я провожу в Интернете часы, но я не Как классические c cook ie, отправленные через .cookie('SESSIONID', jwtBearerToken, {httpOnly:true, secure:false}), должны отправляться в заголовке авторизации. Я ожидал, что за это ответит cookie-parser, но сейчас я сильно сомневаюсь.

Любая помощь приветствуется, заранее спасибо!

1 Ответ

0 голосов
/ 15 апреля 2020

Я не совсем уверен, как эта система настроена на работу и как работает промежуточное программное обеспечение cook ie для JWT, из раздела комментариев урока angular -университета, который я вижу, кто-то прокомментировал авторизацию заголовок также не работает, заключая, что

Safari needs an ending slash on the API's for the Authorization Header to be appended...
Where chrome doesn't need the ending slash and can always add API Headers.
I've appended the slash and it's also working on mobile devices now!

Я бы сказал, что если повар ie вызывает у вас головную боль, может быть, это и не нужно. из l aws, которые регулируют конфиденциальность, и вам нужно будет информировать пользователей о том, что сайт использует куки-файлы, тогда как использование JWT в заголовке «Авторизация» может выполнить sh аутентификацию и авторизацию.

Рассмотрим промежуточное программное обеспечение следующего использования, используя express

import express from 'express';
import cors from 'cors';
import jwt from 'jsonwebtoken';

const app = express();
const JWT_SECRET = 'Your Secret';

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.set('trust proxy', true);
app.disable('x-powered-by');
app.use(cors());

// This can throw an error so always catch it!
function decodeJWT(token) {
  return new Promise((resolve, reject) => {
    jwt.verify(token, JWT_SECRET, (err, obj) => {
      if (err) return reject(err);
      return resolve(obj);
    });
  });
}

function encodeJWT(payload, options = { expiresIn: '30d' }) {
  return new Promise((resolve, reject) => {
    jwt.sign(payload, JWT_SECRET, options, (err, token) => {
      if (err) return reject(err);
      return resolve(token);
    });
  });
}

// This is a middleware function that will activate
// from every request that is sent to the server
// The Angular application can read and write to the 'Authorization' header
app.use(async(req, res, next) => {
  const JWT_TOKEN = req.header('Authorization');
  if (JWT_TOKEN) {
    try {
      // This is the custom property we add to the request
      // Adding this property we can check if the JWT token exists
      // in other API end points of our Express application
      // if this verification does not throw an error, it is valid
      // otherwise, the token will not exist in other API points
      req.JWT = await decodeJWT(JWT_TOKEN);
      res.setHeader('Authroization', JWT_TOKEN)
    } catch (err) {
      console.error(err);
      delete req.JWT;
      res.removeHeader('Authorization');
    }
  }
  next();
});

// Declare all rest API below the middleware
app.post('/api/login', async(req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;
  if (email && password) { // Custom validation can be implemented here
    try {
      const JWT_TOKEN = await encodeJWT({ email: email, auth: true });
      res.setHeader('Authorization', JWT_TOKEN);
      return res.status(200).json(JWT_TOKEN);
    } catch (err) {
      return res.sendStatus(500).json(err);
    }
  }
  res.sendStatus(401).send("Email or Password invalid!"); 
});

app.get('/api/members/only', (req, res, next) => {
  if (req.JWT) { // Or if req.JWT.auth === true
    return res.status(200).send('Hello world!');
  }
  return res.status(401).send('Access Denied');
});

app.listen(8080, () => conosle.log('app listening'));

. В вашем приложении angular вы можете отправлять сообщения по маршруту /api/login по электронной почте и паролю и получать Токен JWT для установки в заголовке «Авторизация».

Служба авторизации в angular может выглядеть следующим образом

@Injectable()
export class AuthService {

    constructor(private http: HttpClient) {
    }

    async login(email: string, password: string) {
      let JWT = await this.http.post('/api/login', {email, password});
      localStorage.set('Authorization', JWT);
      return JWT;
    }

    logout() {
      return localStorage.removeItem('Authorization');
    }

    membersArea() {
      // Also consider a HTTP Interceptor instead of manually setting the headers
      let headers = new Headers();
      headers.append('Content-Type', 'application/json');
      headers.append('Authorization', localStorage.getItem('Authorization'));

      let options = new RequestOptions({ headers: headers });
      return this.http.get('/api/members/only', options);
    }
}

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...