Единый вход Rails Azure Active Directory с аутентификацией приложения Web + iOS - PullRequest
0 голосов
/ 28 апреля 2018

Мне нужно, чтобы пользователь входил в свою учетную запись Azure Active Directory из приложения для iOS и после получения токена передавал информацию на мой сервер rails, который затем аутентифицировал бы пользователя и создал его локальную (Rails) запись пользователя если аутентификация прошла успешно Или, в случае существующего пользователя, он (в идеале) настроил бы переменную Devise current_user, чтобы последующие запросы ресурсов в приложении Rails выполнялись успешно.

У меня есть обе стороны этого уравнения, работающие независимо друг от друга - приложение iOS / Swift 4 использует Microsoft SDK для получения токена - что работает правильно. И сторона рельсов настроена с провайдером Azure Active Directory Omniauth, и он работает правильно, когда вы обращаетесь к нему через браузер. Все идет нормально. (Примечание: оба используют API-интерфейсы Azure AD v1.0: ADAL в iOS и каталог omniauth-azure-active в Rails)

Когда я работал с Omniauth в прошлом - в частности, с помощью провайдера Facebook, я мог просто получить токен на стороне приложения и передать его на сервер Rails, который затем использовал бы график Facebook, чтобы убедиться, что токен был законным с простым запросом GET. Однако при использовании поставщика Microsoft Omniauth не существует аналога. Я обнаружил, что токены и утверждения совпадают между двумя, но я не знаю, как лучше всего указать рельсам, что пользователь легитимен, и его следует создать как current_user в Devise, если детали аутентификации совпадают. Другими словами, какие поля я должен отправить на сторону рельсов, чтобы затем передать их в Azure AD для проверки подлинности пользователя?

Должен ли я попытаться использовать провайдера Omniauth и вернуть ему то, что предоставляет веб-версия (например, хэш omniauth.auth), или я должен написать свой собственный контроллер / действие, которое получает данные аутентификации из приложения, и создать экземпляр пользователя сам после того, как снова проверил пользователя из Rails? Я начал путь с обоих подходов, но пока ничего не получалось.

Нахожусь ли я на правильном пути с любым из этих подходов или есть другие предложения?

Обновление

Я перешел на использование API v2.0 и настроил новое приложение (на apps.dev.microsoft.com), которое использует MSAL на стороне приложения и microsoft_v2_auth на стороне рельсов. Как только я получаю токен доступа от MSAL на стороне приложения, я отправляю его на мой сервер rails в теле POST (через HTTPS). На стороне сервера, я просто выполняю GET для конечной точки «API» Graph API в отдельном действии (не связанном с провайдером Omniauth), используя токен, полученный из приложения, в качестве токена-носителя в заголовке авторизации. Если это возвращается без ошибки, я создаю пользователя, если он не существует, и затем регистрирую его или просто регистрирую, если они существуют. Это похоже на работу.

Я просто использую Omniauth-провайдер для входа в систему.

Так! Этот подход кажется правильным? Мне действительно ничего не нужно от Azure AD, кроме как для аутентификации пользователей. GET-запрос от Graph API с использованием токена, который я получил от приложения, кажется самым простым способом сделать это? Любые другие мысли или проблемы?

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Поскольку меня попросили дать более глубокое понимание этого, я продолжу и опубликую решение, которое я в итоге реализовал.

Добавьте это в свой gemfile:

gem 'omniauth-microsoft_v2_auth'

Добавьте это в конец файла config / devise.rb:

config.omniauth :microsoft_v2_auth, ENV['CLIENT_ID'], ENV['CLIENT_SECRET']

Вам придется добавить эти переменные среды в вашу среду. Обычно я использую драгоценный камень Figaro во время разработки, а затем устанавливаю его через CLI Heroku при развертывании.

Вам нужно будет направить пользователей к вашей аутентификации Azure через контроллер сессий. Добавьте это в свой файл rout.rb:

devise_for :users, :controllers => {sessions: 'sessions', registrations: 'registrations', omniauth_callbacks: "callbacks"} 

devise_scope :user do
  post 'users/sign_in_with_azad_token' => 'sessions#sign_in_with_azad_token'
end

Вот как я реализую действие в моем контроллере сессий:

def sign_in_with_azad_token
    token = params[:token]

    # Use the graph API to ensure this user is legit
    uri = URI("https://graph.microsoft.com/v1.0/me/")
    request = Net::HTTP::Get.new(uri.request_uri)
    request['authorization'] = "Bearer #{token}"

    response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
        http.request(request)
    end

    json = JSON.parse(response.body)

    if json["error"].nil?
        # If no error, user was found
        user = User.from_uid_email(json["id"], json["userPrincipalName"])
        unless user.nil?
            sign_in("user", user)
            respond_to do |format|  
                format.json {  return render :json => {  :success => true, :user => user } }  
            end
        else
            respond_to do |format|  
                format.json {  return render :json => {  :success => false, :message => "You must sign in before continuing" }, status: :unauthorized }  
            end
        end

    else
        respond_to do |format|  
            format.json {  return render :json => {  :success => false, :message => json["error"]["message"]}, status: :unauthorized }  
        end
    end

end

Возможно, вы захотите, чтобы ваши пользователи могли проходить аутентификацию с помощью Microsoft Azure в веб-браузере. В этом случае вам нужно добавить это в ваше новое представление регистрации Devise (мое находится в views / devise / registrations / new.html.erb и views / devise / shared / _links.html.erb):

    <%- if devise_mapping.omniauthable? %>
      <%- resource_class.omniauth_providers.each do |provider| %>
        <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
      <% end -%>
    <% end -%>

Наконец, конечная точка, где мое клиентское приложение выполняет вход в систему, находится в ... [server_url] /users/sign_in_with_azad_token.json

Я достиг этой конечной точки после того, как аутентифицировался с помощью MSAL iOS Framework на стороне приложения и получил токен. Я включаю токен в полезную нагрузку JSON, которая является частью тела запроса. Полезная нагрузка просто:

{
    "token" : "dj9hs0shgkshd93hs92bh7493"

}

Надеюсь, это поможет. Прошло много времени с тех пор, как я работал над этим, поэтому, возможно, я кое-что забыл. Добавьте комментарий к этому ответу, если что-то кажется отсутствующим.

0 голосов
/ 29 апреля 2018

Взгляните на https://github.com/joshsoftware/sso-devise-omniauth-client для идей. Единый вход в систему поддерживается Devise, но вам необходимо настроить некоторые контроллеры и, возможно, собственную стратегию OmniAuth.

Также возможно оформить заказ http://codetheory.in/rails-devise-omniauth-sso/

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