Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Rails + Devise + Angular2: аутентификация

#ruby_on_rails #безопасность #devise #csrf #angular2


У меня просто огромное количество вопросов... Но перед этим нужно описать, что собственно
происходит.

Преамбула

Я пытаюсь научить Angular2 авторизироваться в Rails 5 beta 3 приложении. При этом
Rails работает в режиме API. Как я понимаю, для того, чтобы Devise работал в режиме
API, нужен gem devise_token_auth. Гем я установил и настроил, но вот после этого начались
проблемы:

Unpermitted parameters: user, session

Первое, что я попробовал сделать после настройки, послать простой POST запрос и посмотреть,
что произойдёт. А произошло следующее: 

Processing by DeviseTokenAuth::SessionsController#create as *json*
  Parameters: {"user"=>{"username"=>"demo", "password"=>"[FILTERED]"}, "session"=>{"user"=>{"username"=>"demo",
"password"=>"[FILTERED]"}}}
Unpermitted parameters: user, session
  Rendered devise_token_auth/sessions/create.json (0.2ms)
Completed 401 Unauthorized in 18ms (Views: 3.2ms | ActiveRecord: 0.0ms)


И вот с этого момента я немного не понимаю, с каких это пор я должен прописывать
permit для параметров, которые ActionController::ParamsWrapper создаёт динамически
в качестве обёртки? Более того:

devise_parameter_sanitizer.permit(:sign_in) do |user_params|
  user_params.permit(:user, :session)
end


ничего не меняет. Кто-нибудь сталкивался с подобным ранее?

Authentication header

Покопавшись в документации в поисках решения проблемы я нашёл другую:


  The authentication information should be included by the client in the headers
of each request. The headers follow the RFC 6750 Bearer Token format


Т.е. в заголовке запроса должны быть следующие данные:

"access-token": "wwwww",
"token-type":   "Bearer",
"client":       "xxxxx",
"expiry":       "yyyyy",
"uid":          "zzzzz"


В AngularJS они генерировались модулем ng-token-auth, но как мне сгенерировать их
посредством Angular2, у которого данного модуля нет?



Подводя промежуточный итог (потому что чувствую я, после этих проблем я наткнусь
на их ещё большее количество), вот список моих вопросов:


Как исправить unpermitted parameters: user, session в devise_token_auth?
Как сгенерировать access-token?
Как высчитать expiry и есть ли "rails-way" для времени жизни токена?
Что следует писать в client? Раз уж этот идентификатор позволяет пользователю одновременно
авторизироваться с нескольких устройств, то как он должен выглядить? Что туда следует
записать?





Какие данные следует возвращать клиенту после авторизации (помимо 200)?
Какие ещё подводные камни могут меня ждать при попытке авторизироваться через Rails API?




UPD

Вот запрос, который я шлю:

private _user_session_url = 'auth/sign_in';

login (username: string, password: string) : Observable {
    let body = JSON.stringify({ username: username, password: password });
    // TODO: generate header data.
    let headers = new Headers({
        'Content-Type': 'application/json',
        'accept': 'json'
    });
    let options = new RequestOptions({ headers: headers});

    return this.http.post(this._user_session_url, body, options)
        .map((data: any) => data.json())
        .catch(this.handleError)
}


Как видите, session в теле запроса нет. Его создаёт ActionController::ParamsWrapper

В подтверждение привожу Request Payload:

{"username":"demo","password":"123"}    

    


Ответы

Ответ 1



Согласно краткой документации к devise_token_auth (DTA) POST /sign_in принимает только параметры email и password прямо в корне. То есть, параметры должны выглядеть так: { "email": "foo@example.com", "password": "bar" } Никакой вложенности. Не надо дополнительно настраивать санитайзер и придумывать ненужные ключи. А теперь ответ разом на все оставшиеся вопросы: Token-Type, Access-Token, Client и Expiry. В AngularJS они генерировались модулем ng-token-auth Нет, они генерируются сервером, клиент ничем умным не занимается. Хранятся они в БД (в частично искажённом, но проверяемом виде, как пароли), а обмен ими происходит с помощью заголовков. /sign_in возвращает все интересующие заголовки. Все эти значения вы просто будете передавать туда-сюда (и обновлять, ведь по умолчанию после каждого отдельного запроса токен меняется). Кроме, разве что, Expiry, значением которого можно следить, "когда токен отвалится и потребует обновления", что можно использовать для выкидывания на форму входа. Пользоваться DTA без ng-token-auth можно, но прежде чем за это браться, стоит прочесть документацию к используемым методам. Я пользовался этим гемом ранее и не рекомендую его для случаев, где важна настраиваемость принимаемых и отдаваемых этой системой данных, потому что расширяемость гема близка к нулю.

Комментариев нет:

Отправить комментарий