diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c00b2..3289735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.12] - 2024-10-31 +### Added +- Link Third Party Auth Provider + ## [0.8.11] - 2024-10-23 ### Added - Support for new chains diff --git a/packages/internal/openapi-clients/src/backend-openapi.json b/packages/internal/openapi-clients/src/backend-openapi.json index e8563d1..f294f80 100644 --- a/packages/internal/openapi-clients/src/backend-openapi.json +++ b/packages/internal/openapi-clients/src/backend-openapi.json @@ -191,13 +191,15 @@ "discord", "epic_games", "facebook", + "telegram", "accelbyte", "firebase", "lootlocker", "playfab", "supabase", "custom", - "oidc" + "oidc", + "telegramMiniApp" ], "type": "string" }, @@ -1801,6 +1803,22 @@ "type": "object", "additionalProperties": false }, + "GrantCallbackRequest": { + "properties": { + "code": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "required": [ + "code", + "state" + ], + "type": "object", + "additionalProperties": false + }, "OAuthResponse": { "properties": { "url": { @@ -1821,6 +1839,10 @@ "properties": { "options": { "properties": { + "callbackTo": { + "type": "string", + "description": "A URL to custom handle the provider callback" + }, "queryParams": { "properties": {}, "additionalProperties": { @@ -1851,6 +1873,26 @@ "type": "object", "additionalProperties": false }, + "ThirdPartyLinkRequest": { + "properties": { + "provider": { + "$ref": "#/components/schemas/ThirdPartyOAuthProvider" + }, + "token": { + "type": "string" + }, + "tokenType": { + "type": "string" + } + }, + "required": [ + "provider", + "token", + "tokenType" + ], + "type": "object", + "additionalProperties": false + }, "OAuthProvders": { "enum": [ "google", @@ -1858,13 +1900,15 @@ "facebook", "discord", "epic_games", + "telegram", "accelbyte", "firebase", "lootlocker", "playfab", "supabase", "custom", - "oidc" + "oidc", + "telegramMiniApp" ], "type": "string" }, @@ -9227,6 +9271,9 @@ "security": [ { "pk_access_token": [] + }, + { + "pk_third_party": [] } ], "parameters": [ @@ -9251,6 +9298,58 @@ } } }, + "/iam/v1/oauth/link": { + "post": { + "operationId": "LinkThirdParty", + "responses": { + "201": { + "description": "Success response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthPlayerResponse" + } + } + } + }, + "401": { + "description": "Api key is not valid" + } + }, + "summary": "Initialize Link OAuth.", + "tags": [ + "Authentication" + ], + "security": [ + { + "pk_access_token": [] + }, + { + "pk_third_party": [] + } + ], + "parameters": [ + { + "in": "header", + "name": "x-game", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThirdPartyLinkRequest" + } + } + } + } + } + }, "/iam/v1/oauth/pool": { "post": { "operationId": "PoolOAuth", diff --git a/packages/internal/openapi-clients/src/backend/.openapi-generator/FILES b/packages/internal/openapi-clients/src/backend/.openapi-generator/FILES index 4c3d0ea..1c4fa21 100644 --- a/packages/internal/openapi-clients/src/backend/.openapi-generator/FILES +++ b/packages/internal/openapi-clients/src/backend/.openapi-generator/FILES @@ -181,6 +181,7 @@ models/gas-report-transaction-intents-list-response.ts models/gas-report-transaction-intents.ts models/gas-report.ts models/google-oauth-config.ts +models/grant-callback-request.ts models/grant-oauth-response.ts models/index.ts models/init-embedded-request.ts @@ -315,6 +316,7 @@ models/supabase-auth-config.ts models/telegram-oauth-config.ts models/telegram-third-party-config.ts models/test-trigger200-response.ts +models/third-party-link-request.ts models/third-party-oauth-provider-accelbyte.ts models/third-party-oauth-provider-custom.ts models/third-party-oauth-provider-firebase.ts diff --git a/packages/internal/openapi-clients/src/backend/domain/authentication-api.ts b/packages/internal/openapi-clients/src/backend/domain/authentication-api.ts index 9c592e6..5f00bfc 100644 --- a/packages/internal/openapi-clients/src/backend/domain/authentication-api.ts +++ b/packages/internal/openapi-clients/src/backend/domain/authentication-api.ts @@ -64,6 +64,8 @@ import { SIWERequest } from '../models'; // @ts-ignore import { SignupRequest } from '../models'; // @ts-ignore +import { ThirdPartyLinkRequest } from '../models'; +// @ts-ignore import { ThirdPartyOAuthRequest } from '../models'; // @ts-ignore import { UnlinkEmailRequest } from '../models'; @@ -448,6 +450,47 @@ export const AuthenticationApiAxiosParamCreator = function (configuration?: Conf options: localVarRequestOptions, }; }, + /** + * + * @summary Initialize Link OAuth. + * @param {ThirdPartyLinkRequest} thirdPartyLinkRequest + * @param {string} [xGame] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + linkThirdParty: async (thirdPartyLinkRequest: ThirdPartyLinkRequest, xGame?: string, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'thirdPartyLinkRequest' is not null or undefined + assertParamExists('linkThirdParty', 'thirdPartyLinkRequest', thirdPartyLinkRequest) + const localVarPath = `/iam/v1/oauth/link`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + if (xGame != null) { + localVarHeaderParameter['x-game'] = String(xGame); + } + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(thirdPartyLinkRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * Authenticate a player based on email and password. * @summary Email and password login. @@ -1241,6 +1284,18 @@ export const AuthenticationApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.linkSIWE(sIWEAuthenticateRequest, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @summary Initialize Link OAuth. + * @param {ThirdPartyLinkRequest} thirdPartyLinkRequest + * @param {string} [xGame] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async linkThirdParty(thirdPartyLinkRequest: ThirdPartyLinkRequest, xGame?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.linkThirdParty(thirdPartyLinkRequest, xGame, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * Authenticate a player based on email and password. * @summary Email and password login. @@ -1532,6 +1587,16 @@ export const AuthenticationApiFactory = function (configuration?: Configuration, linkSIWE(requestParameters: AuthenticationApiLinkSIWERequest, options?: AxiosRequestConfig): AxiosPromise { return localVarFp.linkSIWE(requestParameters.sIWEAuthenticateRequest, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary Initialize Link OAuth. + * @param {AuthenticationApiLinkThirdPartyRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + linkThirdParty(requestParameters: AuthenticationApiLinkThirdPartyRequest, options?: AxiosRequestConfig): AxiosPromise { + return localVarFp.linkThirdParty(requestParameters.thirdPartyLinkRequest, requestParameters.xGame, options).then((request) => request(axios, basePath)); + }, /** * Authenticate a player based on email and password. * @summary Email and password login. @@ -1864,6 +1929,27 @@ export interface AuthenticationApiLinkSIWERequest { readonly sIWEAuthenticateRequest: SIWEAuthenticateRequest } +/** + * Request parameters for linkThirdParty operation in AuthenticationApi. + * @export + * @interface AuthenticationApiLinkThirdPartyRequest + */ +export interface AuthenticationApiLinkThirdPartyRequest { + /** + * + * @type {ThirdPartyLinkRequest} + * @memberof AuthenticationApiLinkThirdParty + */ + readonly thirdPartyLinkRequest: ThirdPartyLinkRequest + + /** + * + * @type {string} + * @memberof AuthenticationApiLinkThirdParty + */ + readonly xGame?: string +} + /** * Request parameters for loginEmailPassword operation in AuthenticationApi. * @export @@ -2239,6 +2325,18 @@ export class AuthenticationApi extends BaseAPI { return AuthenticationApiFp(this.configuration).linkSIWE(requestParameters.sIWEAuthenticateRequest, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary Initialize Link OAuth. + * @param {AuthenticationApiLinkThirdPartyRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthenticationApi + */ + public linkThirdParty(requestParameters: AuthenticationApiLinkThirdPartyRequest, options?: AxiosRequestConfig) { + return AuthenticationApiFp(this.configuration).linkThirdParty(requestParameters.thirdPartyLinkRequest, requestParameters.xGame, options).then((request) => request(this.axios, this.basePath)); + } + /** * Authenticate a player based on email and password. * @summary Email and password login. diff --git a/packages/internal/openapi-clients/src/backend/models/auth-provider-response.ts b/packages/internal/openapi-clients/src/backend/models/auth-provider-response.ts index 4e35c02..cbdc2da 100644 --- a/packages/internal/openapi-clients/src/backend/models/auth-provider-response.ts +++ b/packages/internal/openapi-clients/src/backend/models/auth-provider-response.ts @@ -28,13 +28,15 @@ export const AuthProviderResponse = { Discord: 'discord', EpicGames: 'epic_games', Facebook: 'facebook', + Telegram: 'telegram', Accelbyte: 'accelbyte', Firebase: 'firebase', Lootlocker: 'lootlocker', Playfab: 'playfab', Supabase: 'supabase', Custom: 'custom', - Oidc: 'oidc' + Oidc: 'oidc', + TelegramMiniApp: 'telegramMiniApp' } as const; export type AuthProviderResponse = typeof AuthProviderResponse[keyof typeof AuthProviderResponse]; diff --git a/packages/internal/openapi-clients/src/backend/models/grant-callback-request.ts b/packages/internal/openapi-clients/src/backend/models/grant-callback-request.ts new file mode 100644 index 0000000..f094398 --- /dev/null +++ b/packages/internal/openapi-clients/src/backend/models/grant-callback-request.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Openfort API + * Complete Openfort API references and guides can be found at: https://openfort.xyz/docs + * + * The version of the OpenAPI document: 1.0.0 + * Contact: founders@openfort.xyz + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface GrantCallbackRequest + */ +export interface GrantCallbackRequest { + /** + * + * @type {string} + * @memberof GrantCallbackRequest + */ + 'code': string; + /** + * + * @type {string} + * @memberof GrantCallbackRequest + */ + 'state': string; +} + diff --git a/packages/internal/openapi-clients/src/backend/models/index.ts b/packages/internal/openapi-clients/src/backend/models/index.ts index c13b2b5..f13aa76 100644 --- a/packages/internal/openapi-clients/src/backend/models/index.ts +++ b/packages/internal/openapi-clients/src/backend/models/index.ts @@ -155,6 +155,7 @@ export * from './gas-report-list-response'; export * from './gas-report-transaction-intents'; export * from './gas-report-transaction-intents-list-response'; export * from './google-oauth-config'; +export * from './grant-callback-request'; export * from './grant-oauth-response'; export * from './init-embedded-request'; export * from './interaction'; @@ -288,6 +289,7 @@ export * from './supabase-auth-config'; export * from './telegram-oauth-config'; export * from './telegram-third-party-config'; export * from './test-trigger200-response'; +export * from './third-party-link-request'; export * from './third-party-oauth-provider'; export * from './third-party-oauth-provider-accelbyte'; export * from './third-party-oauth-provider-custom'; diff --git a/packages/internal/openapi-clients/src/backend/models/oauth-init-request-options.ts b/packages/internal/openapi-clients/src/backend/models/oauth-init-request-options.ts index 7a79cc3..3dd7fcd 100644 --- a/packages/internal/openapi-clients/src/backend/models/oauth-init-request-options.ts +++ b/packages/internal/openapi-clients/src/backend/models/oauth-init-request-options.ts @@ -20,6 +20,12 @@ * @interface OAuthInitRequestOptions */ export interface OAuthInitRequestOptions { + /** + * A URL to custom handle the provider callback + * @type {string} + * @memberof OAuthInitRequestOptions + */ + 'callbackTo'?: string; /** * An object of query params * @type {{ [key: string]: string; }} diff --git a/packages/internal/openapi-clients/src/backend/models/oauth-provders.ts b/packages/internal/openapi-clients/src/backend/models/oauth-provders.ts index 46784dd..39df710 100644 --- a/packages/internal/openapi-clients/src/backend/models/oauth-provders.ts +++ b/packages/internal/openapi-clients/src/backend/models/oauth-provders.ts @@ -26,13 +26,15 @@ export const OAuthProvders = { Facebook: 'facebook', Discord: 'discord', EpicGames: 'epic_games', + Telegram: 'telegram', Accelbyte: 'accelbyte', Firebase: 'firebase', Lootlocker: 'lootlocker', Playfab: 'playfab', Supabase: 'supabase', Custom: 'custom', - Oidc: 'oidc' + Oidc: 'oidc', + TelegramMiniApp: 'telegramMiniApp' } as const; export type OAuthProvders = typeof OAuthProvders[keyof typeof OAuthProvders]; diff --git a/packages/internal/openapi-clients/src/backend/models/third-party-link-request.ts b/packages/internal/openapi-clients/src/backend/models/third-party-link-request.ts new file mode 100644 index 0000000..308ecbb --- /dev/null +++ b/packages/internal/openapi-clients/src/backend/models/third-party-link-request.ts @@ -0,0 +1,47 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Openfort API + * Complete Openfort API references and guides can be found at: https://openfort.xyz/docs + * + * The version of the OpenAPI document: 1.0.0 + * Contact: founders@openfort.xyz + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import { ThirdPartyOAuthProvider } from './third-party-oauth-provider'; + +/** + * + * @export + * @interface ThirdPartyLinkRequest + */ +export interface ThirdPartyLinkRequest { + /** + * + * @type {ThirdPartyOAuthProvider} + * @memberof ThirdPartyLinkRequest + */ + 'provider': ThirdPartyOAuthProvider; + /** + * + * @type {string} + * @memberof ThirdPartyLinkRequest + */ + 'token': string; + /** + * + * @type {string} + * @memberof ThirdPartyLinkRequest + */ + 'tokenType': string; +} + + + diff --git a/sdk/package.json b/sdk/package.json index 6f42e21..357319a 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@openfort/openfort-js", - "version": "0.8.11", + "version": "0.8.12", "author": "Openfort (https://www.openfort.xyz)", "bugs": "https://github.com/openfort-xyz/openfort-js/issues", "repository": "openfort-xyz/openfort-js.git", diff --git a/sdk/src/authManager.ts b/sdk/src/authManager.ts index 50051ab..04882da 100644 --- a/sdk/src/authManager.ts +++ b/sdk/src/authManager.ts @@ -453,9 +453,42 @@ export default class AuthManager { return response.data; } + public async linkThirdParty( + auth: Authentication, + provider: ThirdPartyOAuthProvider, + playerToken: string, + tokenType: TokenType, + ecosystemGame?: string, + ): Promise { + const request = { + thirdPartyLinkRequest: { + provider, + token: playerToken, + tokenType, + }, + }; + const response = await this.backendApiClients.authenticationApi.linkThirdParty( + request, + { + headers: { + authorization: `Bearer ${this.publishableKey}`, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-player-token': auth.token, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-auth-provider': auth.thirdPartyProvider || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-token-type': auth.thirdPartyTokenType || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-game': ecosystemGame || undefined, + }, + }, + ); + return response.data; + } + public async linkOAuth( + auth: Authentication, provider: OAuthProvider, - playerToken: string, options?: InitializeOAuthOptions, ecosystemGame?: string, ): Promise { @@ -472,7 +505,11 @@ export default class AuthManager { headers: { authorization: `Bearer ${this.publishableKey}`, // eslint-disable-next-line @typescript-eslint/naming-convention - 'x-player-token': playerToken, + 'x-player-token': auth.token, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-auth-provider': auth.thirdPartyProvider || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'x-token-type': auth.thirdPartyTokenType || undefined, // eslint-disable-next-line @typescript-eslint/naming-convention 'x-game': ecosystemGame || undefined, }, diff --git a/sdk/src/openfort.ts b/sdk/src/openfort.ts index 85347c0..66a47a6 100644 --- a/sdk/src/openfort.ts +++ b/sdk/src/openfort.ts @@ -386,19 +386,44 @@ export class Openfort { * Initializes an OAuth linking process. * * @param provider - OAuth provider. - * @param authToken - Authentication token. * @param options - Additional options for initialization. * @param ecosystemGame - In case of ecosystem, the game that wants to authenticate. * @returns An InitAuthResponse object. */ public async initLinkOAuth( { - provider, authToken, options, ecosystemGame, + provider, options, ecosystemGame, }: { provider: OAuthProvider; authToken: string; options?: InitializeOAuthOptions, ecosystemGame?: string }, ): Promise { - return await this.authManager.linkOAuth(provider, authToken, options, ecosystemGame); + const auth = Authentication.fromStorage(this.storage); + if (!auth) { + throw new OpenfortError('No authentication found', OpenfortErrorType.NOT_LOGGED_IN_ERROR); + } + + return await this.authManager.linkOAuth(auth, provider, options, ecosystemGame); + } + + /** + * Links a Third-Party authentication provider to the account. + * + * @param provider - Third-party provider. + * @param token - Third-party token. + * @param tokenType - Type of the token (idToken or customToken). + * @returns An AuthPlayerResponse object. + */ + public async linkThirdPartyProvider( + { + provider, token, tokenType, + }: { provider: ThirdPartyOAuthProvider; token: string; tokenType: TokenType }, + ): Promise { + const auth = Authentication.fromStorage(this.storage); + if (!auth) { + throw new OpenfortError('No authentication found', OpenfortErrorType.NOT_LOGGED_IN_ERROR); + } + + return await this.authManager.linkThirdParty(auth, provider, token, tokenType); } /** diff --git a/sdk/src/types.ts b/sdk/src/types.ts index 61b9331..eacfa0c 100644 --- a/sdk/src/types.ts +++ b/sdk/src/types.ts @@ -139,6 +139,7 @@ export enum OAuthProvider { DISCORD = 'discord', EPIC_GAMES = 'epic_games', TELEGRAM = 'telegram', + LINE = 'line', } export interface NextActionPayload { diff --git a/sdk/src/version.ts b/sdk/src/version.ts index 9e8beef..742df8b 100644 --- a/sdk/src/version.ts +++ b/sdk/src/version.ts @@ -1,2 +1,2 @@ -export const VERSION = '0.8.11'; +export const VERSION = '0.8.12'; export const PACKAGE = '@openfort/openfort-js';