You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails+iOS应用Azure Active Directory SSO认证对接需求

Alright, let's walk through how to connect your iOS app's Azure AD login flow with your Rails backend to handle user authentication, user record management, and session setup. I've broken this down into clear, actionable steps that tie both ends together seamlessly:

1. iOS端:传递Azure AD令牌到Rails服务器

Assuming your iOS app already uses MSAL (or another Azure AD auth library) to get tokens, here's how to send them to your Rails backend:

  • First, grab the access token from your login result (MSAL gives you an MSALResult object with this). You can also pull basic user info like email/name from the associated MSALAccount to pass along as optional context.
  • Send a POST request to a dedicated Rails auth endpoint (e.g., /api/auth/azure_ad), putting the access token in the Authorization header using the Bearer scheme. Here's a quick Swift example:
guard let accessToken = msalResult.accessToken,
      let account = msalResult.account else { return }

let authUrl = URL(string: "https://your-rails-app-domain.com/api/auth/azure_ad")!
var request = URLRequest(url: authUrl)
request.httpMethod = "POST"
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

// Optional: Send basic user info to avoid re-parsing it from the token later
let userPayload = [
    "email": account.username,
    "full_name": account.name
]
request.httpBody = try? JSONSerialization.data(withJSONObject: userPayload)

// Execute the request and handle the server response
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
        // Success! Store any session tokens/cookies from the response for future requests
    } else {
        // Handle errors (e.g., invalid token, server issue)
    }
}
task.resume()
2. Rails端:验证令牌并管理用户

Now let's handle the token validation, user lookup/creation, and Devise session setup on the Rails side:

2.1 验证Azure AD令牌的有效性

First, you'll need to validate the token's signature, issuer, and audience to make sure it's legitimate. You can use the jwt gem for this, and cache Azure AD's public keys to avoid repeated network calls. Here's how to implement this in a controller:

# app/controllers/api/auth_controller.rb
class Api::AuthController < ApplicationController
  skip_before_action :authenticate_user!, only: [:azure_ad_login]

  def azure_ad_login
    # Extract the token from the Authorization header
    token = request.headers['Authorization']&.split('Bearer ')&.last
    return render json: { error: "Missing auth token" }, status: :unauthorized unless token

    begin
      # Fetch and cache Azure AD's public keys (do this once, not on every request!)
      azure_ad_keys = JSON.parse(URI.open("https://login.microsoftonline.com/your-tenant-id/discovery/v2.0/keys").read)
      public_key = JWT::JWK::Set.new(azure_ad_keys).find do |jwk|
        JWT.decode(token, nil, false, { algorithm: "RS256" })[0]["kid"] == jwk["kid"]
      end.to_key

      # Decode and validate the token
      decoded_token = JWT.decode(
        token,
        public_key,
        true,
        algorithm: "RS256",
        iss: "https://login.microsoftonline.com/your-tenant-id/v2.0",
        aud: "your-azure-ad-client-id", # This should match your Azure AD app's client ID
        verify_iss: true,
        verify_aud: true
      )
      user_data = decoded_token[0]
    rescue JWT::DecodeError, URI::Error => e
      return render json: { error: "Invalid or expired token" }, status: :unauthorized
    end

2.2 查找或创建本地用户

Use a unique identifier from the Azure AD token (like the oid field, which is the user's immutable Azure AD object ID) to find or create a local Rails user:

# Use Azure AD's oid as the unique identifier (more reliable than email)
      azure_ad_oid = user_data["oid"]
      user = User.find_or_create_by(azure_ad_oid: azure_ad_oid) do |new_user|
        new_user.email = user_data["email"]
        new_user.name = user_data["name"]
        # Devise requires a password; generate a random one since users won't use local auth
        new_user.password = Devise.friendly_token.first(16)
      end

2.3 设置Devise的current_user

Finally, sign the user in to set up the Devise session. The approach depends on whether you're building a traditional cookie-based app or an API:

# For cookie-based web apps (if iOS uses a WKWebView):
      sign_in(user, scope: :user)
      render json: { message: "Login successful", user: user }, status: :ok

      # For API apps (using Devise Token Auth):
      # user.generate_auth_token!
      # user.save!
      # render json: { user: user, auth_token: user.authentication_token }, status: :ok
    end
  end
end
3. Securing Subsequent Requests
  • iOS Side: If using cookies, URLSession will automatically persist the session cookie for future requests. If using token auth, include the Rails-generated auth token in the Authorization header for every protected request.
  • Rails Side: Protect your resources with Devise's authenticate_user! filter to ensure only logged-in users can access them:
class Api::ProtectedResourcesController < ApplicationController
  before_action :authenticate_user!

  def index
    # Return your protected data here
    render json: { resources: YourModel.all }
  end
end
Key Notes to Remember
  • Double-check your Azure AD app configuration: Make sure your Rails server's domain is allowed in the app's redirect URIs (if using implicit flow) and that the audience (aud) in your token validation matches your Azure AD client ID.
  • Cache Azure AD's public keys! Fetching them on every request will slow down your backend. Use Rails.cache to store them for a few hours.
  • Handle token expiration on iOS: If your Rails server returns a 401 Unauthorized response, trigger MSAL's token refresh flow to get a new access token before retrying the request.

内容的提问来源于stack exchange,提问作者Matt Long

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:28:55