From 0934e14e2e10067aa064085b57f072d955503110 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Fri, 30 May 2025 15:35:05 -0700 Subject: [PATCH 1/4] The microsoft client is now working. --- Sources/OAuthKit/OAuth.swift | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index a3162df..a956d6f 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -436,22 +436,24 @@ public extension OAuth { func requestAccessToken(provider: Provider, code: String) async -> Result { // Publish the state publish(state: .requestingAccessToken(provider)) - guard var urlComponents = URLComponents(string: provider.accessTokenURL.absoluteString) else { - publish(state: .empty) - return .failure(.malformedURL) - } - var queryItems = [URLQueryItem]() - queryItems.append(URLQueryItem(name: "client_id", value: provider.clientID)) - queryItems.append(URLQueryItem(name: "client_secret", value: provider.clientSecret)) - queryItems.append(URLQueryItem(name: "code", value: code)) - queryItems.append(URLQueryItem(name: "redirect_uri", value: provider.redirectURI)) - queryItems.append(URLQueryItem(name: "grant_type", value: "authorization_code")) - urlComponents.queryItems = queryItems - guard let url = urlComponents.url else { + + guard let url = URL(string: provider.accessTokenURL.absoluteString) else { publish(state: .empty) return .failure(.malformedURL) } + + var urlComponents = URLComponents() + urlComponents.queryItems = [ + URLQueryItem(name: "client_id", value: provider.clientID), + URLQueryItem(name: "client_secret", value: provider.clientSecret), + URLQueryItem(name: "code", value: code), + URLQueryItem(name: "redirect_uri", value: provider.redirectURI), + URLQueryItem(name: "grant_type", value: "authorization_code") + ] + + // Encode the url components as 'application/x-www-form-urlencoded' body var request = URLRequest(url: url) + request.httpBody = urlComponents.query?.data(using: .utf8) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Accept") guard let (data, _) = try? await urlSession.data(for: request) else { From 65f7e827def0f0b6044a023235961e1b4d750286 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Fri, 30 May 2025 15:36:54 -0700 Subject: [PATCH 2/4] Added Microsoft provider template. --- Tests/OAuthKitTests/Resources/oauth.json | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Tests/OAuthKitTests/Resources/oauth.json b/Tests/OAuthKitTests/Resources/oauth.json index 5effaff..e24ff32 100644 --- a/Tests/OAuthKitTests/Resources/oauth.json +++ b/Tests/OAuthKitTests/Resources/oauth.json @@ -21,8 +21,21 @@ "clientSecret": "CLIENT_SECRET", "redirectURI": "https://github.com/codefiesta/", "scope": [ - "https://www.googleapis.com/auth/userinfo.email", - "https://www.googleapis.com/auth/userinfo.profile", + "email", + "profile", + "openid" + ] + }, + { + "id": "Microsoft", + "authorizationURL": "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize", + "accessTokenURL": "https://login.microsoftonline.com/consumers/oauth2/v2.0/token", + "clientID": "CLIENT_ID", + "clientSecret": "CLIENT_SECRET", + "redirectURI": "https://github.com/codefiesta/", + "scope": [ + "email", + "profile", "openid" ] } From a14003733f3dfff60b4122e9f350494dbe8dadad Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Fri, 30 May 2025 15:43:42 -0700 Subject: [PATCH 3/4] Updating README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 706ada4..33397bb 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ Although OAuthKit will automatically try to load the `oauth.json` file found ins * **Important**: When creating a Google OAuth2 application from the [Google API Console](https://console.developers.google.com/) create an OAuth 2.0 Client type of Web Application (not iOS). * [Instagram](https://developers.facebook.com/docs/instagram-basic-display-api/guides/getting-access-tokens-and-permissions) * [Microsoft](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow) + * **Important**: When registering an application inside the [Microsoft Azure Portal](https://portal.azure.com/) it's important to choose a **Redirect URI** as **Web** otherwise the `/token` endpoint will return an error when sending the `client_secret` in the body payload. * [Slack](https://api.slack.com/authentication/oauth-v2) * [Twitter](https://developer.x.com/en/docs/authentication/oauth-2-0) From a7d5d943f978ff1201ca0e8c2740d4e458cff37a Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Fri, 30 May 2025 15:53:54 -0700 Subject: [PATCH 4/4] Lint fixes --- Sources/OAuthKit/OAuth.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index a956d6f..ce2497b 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -436,12 +436,12 @@ public extension OAuth { func requestAccessToken(provider: Provider, code: String) async -> Result { // Publish the state publish(state: .requestingAccessToken(provider)) - + guard let url = URL(string: provider.accessTokenURL.absoluteString) else { publish(state: .empty) return .failure(.malformedURL) } - + var urlComponents = URLComponents() urlComponents.queryItems = [ URLQueryItem(name: "client_id", value: provider.clientID),