SoFunction
Updated on 2025-04-12

iOS Moya method to implement OAuth request

0. Origin

Open Authorization (OAuth) is an open standard that allows users to allow third-party applications to access private resources (such as photos, videos, contact lists) stored on a website without providing username and password to third-party applications.

As a third-party software, providing OAuth login for users is a better choice, which can effectively eliminate users' concerns about the leakage of personal account passwords, and can also effectively avoid users' repeated login, thereby increasing user comfort and improving user stickiness.

1. Environment

The project uses the MVVM architecture, introduces the Rx family bucket, and the network request framework uses theMoya , and handle Oauth-related librariesOAuth2

2. OAuth2 part

See the OAuth2 libraryREADME , complete the OAuth information configuration:

let oauth2 = OAuth2CodeGrant(settings: [
  "client_id": "my_swift_app",
  "client_secret": "C7447242",
  "authorize_uri": "/login/oauth/authorize",
  "token_uri": "/login/oauth/access_token",
  "redirect_uris": ["myapp://oauth/callback"],
  "scope": "user repo:status",
  "secret_in_body": true,
  "keychain": false,
] as OAuth2JSON)

At the same time, because Moya's underlying network request implementation is based on Alamofire, we can refer to the documentation provided by OAuth2Alamofire 4 · p2/OAuth2 Wiki · GitHub Complete the relevant configuration, the key code is as follows:

import Foundation
import OAuth2
import Alamofire


class OAuth2RetryHandler: RequestRetrier, RequestAdapter {
  
  let loader: OAuth2DataLoader
  
  init(oauth2: OAuth2) {
    loader = OAuth2DataLoader(oauth2: oauth2)
  }
  
  /// Intercept 401 and do an OAuth2 authorization.
  public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
    if let response = ?.response as? HTTPURLResponse, 401 == , let req =  {
      var dataRequest = OAuth2DataRequest(request: req, callback: { _ in })
       = completion
      (request: dataRequest)
      () { authParams, error in
        () { req in
          if let comp =  as? RequestRetryCompletion {
            comp(nil != authParams, 0.0)
          }
        }
      }
    }
    else {
      completion(false, 0.0)  // not a 401, not our problem
    }
  }
  
  /// Sign the request with the access token.
  public func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
    guard nil != loader. else {
      return urlRequest
    }
    return try (with: loader.oauth2)  // "try" added in 3.0.2
  }
}

3. Moya part

Moya's provider can be passed into a SessionManager when initialized, so refer to the documentation, you can first use OAuth2 to generate a specific SessionManager:

func getManager() -> SessionManager {

    let oauth2 = OAuth2CodeGrant(settings: [
      "client_id": "my_swift_app",
      "client_secret": "C7447242",
      "authorize_uri": "/login/oauth/authorize",
      "token_uri": "/login/oauth/access_token",
      "redirect_uris": ["myapp://oauth/callback"],
      "scope": "user repo:status",
      "secret_in_body": true,
      "keychain": false,
      ] as OAuth2JSON)

    let sessionManager = SessionManager()
    let oauthHandler = OAuth2Handler(oauth2: oauth2)
     = oauthHandler
     = oauthHandler
    return sessionManager
  }

Then generate a provider with OAuth:

fileprivate lazy var provider: MoyaProvider = {
  return MoyaProvider<API>(manager: (),
              plugins: [NetworkLoggerPlugin()])
}()

use

Just use the generated provider to send the request, and Moya can automatically process the OAuth authentication information.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.