🔐 Using Microsoft Graph API to Automate 2FA Retrieval

Two-factor authentication (2FA) is essential for security, but manually retrieving codes can be tedious during development and testing. In this post, we'll explore how to use Microsoft Graph API to programmatically access 2FA codes from Microsoft Authenticator, making your development workflow more efficient while maintaining security.

🚨 Important Security Notice

Warning: This approach should only be used in development/testing environments. Never automate 2FA retrieval in production systems as it defeats the purpose of two-factor authentication.

📋 Prerequisites

Before we start, ensure you have:

  • ✅ Azure AD tenant with admin access
  • ✅ Microsoft Authenticator app configured
  • ✅ Basic understanding of OAuth 2.0
  • ✅ Ruby/Rails development environment

🔧 Setting Up Azure App Registration

1. Create App Registration

Navigate to Azure Portal → Azure Active Directory → App registrations → New registration:

Name: "2FA Automation Tool"
Supported account types: Single tenant
Redirect URI: http://localhost:3000/auth/callback

2. Configure API Permissions

Add the following Microsoft Graph permissions:

  • User.Read - Read user profile
  • UserAuthenticationMethod.Read.All - Read authentication methods

Note: These permissions require admin consent in most organizations.

💎 Ruby Implementation

Setting Up the Graph Client

First, add the required gems to your Gemfile:

# Gemfile
gem 'httparty'
gem 'oauth2'

Create a service class for Microsoft Graph API:

class MicrosoftGraphService
  include HTTParty
  base_uri 'https://graph.microsoft.com/v1.0'

  def initialize(access_token)
    @access_token = access_token
    @headers = {
      'Authorization' => "Bearer #{@access_token}",
      'Content-Type' => 'application/json'
    }
  end

  def get_user_profile
    response = self.class.get('/me', headers: @headers)
    handle_response(response)
  end

  def get_authentication_methods
    response = self.class.get('/me/authentication/methods', headers: @headers)
    handle_response(response)
  end

  private

  def handle_response(response)
    if response.success?
      JSON.parse(response.body)
    else
      raise "API Error: #{response.code} - #{response.message}"
    end
  end
end

OAuth 2.0 Authentication Flow

Implement the OAuth flow to get access tokens:

class AuthController < ApplicationController
  def authorize
    client = OAuth2::Client.new(
      ENV['AZURE_CLIENT_ID'],
      ENV['AZURE_CLIENT_SECRET'],
      site: 'https://login.microsoftonline.com',
      authorize_url: "/#{ENV['AZURE_TENANT_ID']}/oauth2/v2.0/authorize",
      token_url: "/#{ENV['AZURE_TENANT_ID']}/oauth2/v2.0/token"
    )

    redirect_to client.auth_code.authorize_url(
      redirect_uri: ENV['REDIRECT_URI'],
      scope: 'User.Read UserAuthenticationMethod.Read.All'
    )
  end

  def callback
    # Handle the callback and exchange code for token
    # Store token securely for API calls
  end
end

🔍 Retrieving 2FA Codes

Once authenticated, you can retrieve authentication methods:

def get_current_2fa_code
  graph_service = MicrosoftGraphService.new(current_user.access_token)
  
  auth_methods = graph_service.get_authentication_methods
  
  # Find Microsoft Authenticator method
  authenticator_method = auth_methods['value'].find do |method|
    method['@odata.type'] == '#microsoft.graph.microsoftAuthenticatorAuthenticationMethod'
  end

  if authenticator_method
    # Extract current TOTP code
    extract_totp_code(authenticator_method)
  else
    raise "Microsoft Authenticator not found"
  end
end

⚡ Integration with Rails App

Create a helper method for development environments:

module DevelopmentHelper
  def auto_fill_2fa_code
    return unless Rails.env.development?
    
    begin
      code = TwoFactorService.get_current_code
      render json: { code: code }
    rescue => e
      render json: { error: e.message }, status: :unprocessable_entity
    end
  end
end

🔐 Security Best Practices

  • 🔒 Store tokens securely using Rails credentials
  • ⏰ Implement token refresh logic
  • 🚫 Never use in production environments
  • 🔄 Rotate API credentials regularly
  • 📝 Log all API access for auditing

🚧 Limitations & Considerations

  • Requires organizational admin consent
  • Limited to Microsoft-based 2FA solutions
  • Rate limiting applies to Graph API calls
  • Not suitable for production use cases

📚 Resources