Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoginOptions additions #44

Merged
merged 8 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 61 additions & 39 deletions src/internal/http/DescopeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ class DescopeClient: HTTPClient {
])
}

func otpSignIn(with method: DeliveryMethod, loginId: String) async throws -> MaskedAddress {
return try await post("auth/otp/signin/\(method.rawValue)", body: [
"loginId": loginId
func otpSignIn(with method: DeliveryMethod, loginId: String, refreshJwt: String?, options: LoginOptions?) async throws -> MaskedAddress {
return try await post("auth/otp/signin/\(method.rawValue)", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"loginOptions": options?.dictValue,
])
}

func otpSignUpIn(with method: DeliveryMethod, loginId: String) async throws -> MaskedAddress {
return try await post("auth/otp/signup-in/\(method.rawValue)", body: [
"loginId": loginId
func otpSignUpIn(with method: DeliveryMethod, loginId: String, refreshJwt: String?, options: LoginOptions?) async throws -> MaskedAddress {
return try await post("auth/otp/signup-in/\(method.rawValue)", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"loginOptions": options?.dictValue,
])
}

Expand Down Expand Up @@ -71,10 +73,11 @@ class DescopeClient: HTTPClient {
])
}

func totpVerify(loginId: String, code: String) async throws -> JWTResponse {
return try await post("auth/totp/verify", body: [
func totpVerify(loginId: String, code: String, refreshJwt: String?, options: LoginOptions?) async throws -> JWTResponse {
return try await post("auth/totp/verify", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"code": code,
"loginOptions": options?.dictValue,
])
}

Expand Down Expand Up @@ -138,25 +141,27 @@ class DescopeClient: HTTPClient {

// MARK: - Magic Link

func magicLinkSignUp(with method: DeliveryMethod, loginId: String, details: SignUpDetails?, uri: String?) async throws -> MaskedAddress {
func magicLinkSignUp(with method: DeliveryMethod, loginId: String, details: SignUpDetails?, redirectURL: String?) async throws -> MaskedAddress {
return try await post("auth/magiclink/signup/\(method.rawValue)", body: [
"loginId": loginId,
"user": details?.dictValue,
"uri": uri,
"redirectUrl": redirectURL,
])
}

func magicLinkSignIn(with method: DeliveryMethod, loginId: String, uri: String?) async throws -> MaskedAddress {
return try await post("auth/magiclink/signin/\(method.rawValue)", body: [
func magicLinkSignIn(with method: DeliveryMethod, loginId: String, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> MaskedAddress {
return try await post("auth/magiclink/signin/\(method.rawValue)", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"uri": uri,
"redirectUrl": redirectURL,
"loginOptions": options?.dictValue,
])
}

func magicLinkSignUpOrIn(with method: DeliveryMethod, loginId: String, uri: String?) async throws -> MaskedAddress {
return try await post("auth/magiclink/signup-in/\(method.rawValue)", body: [
func magicLinkSignUpOrIn(with method: DeliveryMethod, loginId: String, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> MaskedAddress {
return try await post("auth/magiclink/signup-in/\(method.rawValue)", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"uri": uri,
"redirectUrl": redirectURL,
"loginOptions": options?.dictValue,
])
}

Expand All @@ -166,22 +171,22 @@ class DescopeClient: HTTPClient {
])
}

func magicLinkUpdateEmail(_ email: String, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> MaskedAddress {
func magicLinkUpdateEmail(_ email: String, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> MaskedAddress {
return try await post("auth/magiclink/update/email", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"email": email,
"uri": uri,
"redirectUrl": redirectURL,
"addToLoginIDs": options.contains(.addToLoginIds),
"onMergeUseExisting": options.contains(.onMergeUseExisting),
])
}

func magicLinkUpdatePhone(_ phone: String, with method: DeliveryMethod, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> MaskedAddress {
func magicLinkUpdatePhone(_ phone: String, with method: DeliveryMethod, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> MaskedAddress {
try method.ensurePhoneMethod()
return try await post("auth/magiclink/update/phone/\(method.rawValue)", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"phone": phone,
"uri": uri,
"redirectUrl": redirectURL,
"addToLoginIDs": options.contains(.addToLoginIds),
"onMergeUseExisting": options.contains(.onMergeUseExisting),
])
Expand All @@ -195,33 +200,35 @@ class DescopeClient: HTTPClient {
var maskedEmail: String
}

func enchantedLinkSignUp(loginId: String, details: SignUpDetails?, uri: String?) async throws -> EnchantedLinkResponse {
func enchantedLinkSignUp(loginId: String, details: SignUpDetails?, redirectURL: String?) async throws -> EnchantedLinkResponse {
return try await post("auth/enchantedlink/signup/email", body: [
"loginId": loginId,
"user": details?.dictValue,
"uri": uri,
"redirectUrl": redirectURL,
])
}

func enchantedLinkSignIn(loginId: String, uri: String?) async throws -> EnchantedLinkResponse {
try await post("auth/enchantedlink/signin/email", body: [
func enchantedLinkSignIn(loginId: String, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> EnchantedLinkResponse {
try await post("auth/enchantedlink/signin/email", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"uri": uri,
"redirectUrl": redirectURL,
"loginOptions": options?.dictValue,
])
}

func enchantedLinkSignUpOrIn(loginId: String, uri: String?) async throws -> EnchantedLinkResponse {
try await post("auth/enchantedlink/signup-in/email", body: [
func enchantedLinkSignUpOrIn(loginId: String, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> EnchantedLinkResponse {
try await post("auth/enchantedlink/signup-in/email", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"uri": uri,
"redirectUrl": redirectURL,
"loginOptions": options?.dictValue,
])
}

func enchantedLinkUpdateEmail(_ email: String, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> EnchantedLinkResponse {
func enchantedLinkUpdateEmail(_ email: String, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> EnchantedLinkResponse {
return try await post("auth/enchantedlink/update/email", headers: authorization(with: refreshJwt), body: [
"loginId": loginId,
"email": email,
"uri": uri,
"redirectUrl": redirectURL,
"addToLoginIDs": options.contains(.addToLoginIds),
"onMergeUseExisting": options.contains(.onMergeUseExisting),
])
Expand All @@ -239,11 +246,11 @@ class DescopeClient: HTTPClient {
var url: String
}

func oauthStart(provider: OAuthProvider, redirectURL: String?) async throws -> OAuthResponse {
return try await post("auth/oauth/authorize", params: [
func oauthStart(provider: OAuthProvider, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> OAuthResponse {
return try await post("auth/oauth/authorize", headers: authorization(with: refreshJwt), params: [
"provider": provider.rawValue,
"redirectURL": redirectURL,
])
"redirectUrl": redirectURL
], body: options?.dictValue ?? [:])
}

func oauthExchange(code: String) async throws -> JWTResponse {
Expand All @@ -258,11 +265,11 @@ class DescopeClient: HTTPClient {
var url: String
}

func ssoStart(emailOrTenantName: String, redirectURL: String?) async throws -> OAuthResponse {
return try await post("auth/saml/authorize", params: [
func ssoStart(emailOrTenantName: String, redirectURL: String?, refreshJwt: String?, options: LoginOptions?) async throws -> OAuthResponse {
return try await post("auth/saml/authorize", headers: authorization(with: refreshJwt), params: [
"tenant": emailOrTenantName,
"redirectURL": redirectURL,
])
"redirectUrl": redirectURL
], body: options?.dictValue ?? [:])
}

func ssoExchange(code: String) async throws -> JWTResponse {
Expand Down Expand Up @@ -340,6 +347,20 @@ class DescopeClient: HTTPClient {
var maskedPhone: String?
}

struct LoginOptions {
var stepup: Bool = false
var mfa: Bool = false
var customClaims: [String: Any] = [:]

var dictValue: [String: Any?] {
return [
"stepup": stepup ? true : nil,
"mfa": mfa ? true : nil,
"customClaims": customClaims.isEmpty ? nil : customClaims,
]
}
}

// MARK: - Internal

override var basePath: String {
Expand All @@ -358,7 +379,8 @@ class DescopeClient: HTTPClient {
return DescopeError(errorResponse: data)
}

private func authorization(with value: String) -> [String: String] {
private func authorization(with value: String?) -> [String: String] {
guard let value else { return [:] }
return ["Authorization": "Bearer \(config.projectId):\(value)"]
}
}
Expand Down
57 changes: 57 additions & 0 deletions src/internal/others/Deprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,60 @@ public typealias User = SignUpDetails
/// See the documentation for `PasswordPolicyResponse`.
@available(*, unavailable, renamed: "PasswordPolicyResponse")
public typealias PasswordPolicy = PasswordPolicyResponse

public extension DescopeOTP {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signIn(with method: DeliveryMethod, loginId: String) async throws -> String {
return try await signIn(with: method, loginId: loginId, options: [])
}

@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signUpOrIn(with method: DeliveryMethod, loginId: String) async throws -> String {
return try await signUpOrIn(with: method, loginId: loginId, options: [])
}
}

public extension DescopeTOTP {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func verify(loginId: String, code: String) async throws -> AuthenticationResponse {
return try await verify(loginId: loginId, code: code, options: [])
}
}

public extension DescopeMagicLink {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signIn(with method: DeliveryMethod, loginId: String, redirectURL: String?) async throws -> String {
return try await signIn(with: method, loginId: loginId, redirectURL: redirectURL, options: [])
}

@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signUpOrIn(with method: DeliveryMethod, loginId: String, redirectURL: String?) async throws -> String {
return try await signUpOrIn(with: method, loginId: loginId, redirectURL: redirectURL, options: [])
}
}

public extension DescopeEnchantedLink {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signIn(loginId: String, redirectURL: String?) async throws -> EnchantedLinkResponse {
return try await signIn(loginId: loginId, redirectURL: redirectURL, options: [])
}

@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func signUpOrIn(loginId: String, redirectURL: String?) async throws -> EnchantedLinkResponse {
return try await signUpOrIn(loginId: loginId, redirectURL: redirectURL, options: [])
}
}

public extension DescopeOAuth {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func start(provider: OAuthProvider, redirectURL: String?) async throws -> String {
return try await start(provider: provider, redirectURL: redirectURL, options: [])
}
}

public extension DescopeSSO {
@available(*, deprecated, message: "Pass a value (or an empty array) for the options parameter")
func start(emailOrTenantName: String, redirectURL: String?) async throws -> String {
return try await start(emailOrTenantName: emailOrTenantName, redirectURL: redirectURL, options: [])
}
}
18 changes: 10 additions & 8 deletions src/internal/routes/EnchantedLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ class EnchantedLink: Route, DescopeEnchantedLink {
self.client = client
}

func signUp(loginId: String, details: SignUpDetails?, uri: String?) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkSignUp(loginId: loginId, details: details, uri: uri).convert()
func signUp(loginId: String, details: SignUpDetails?, redirectURL: String?) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkSignUp(loginId: loginId, details: details, redirectURL: redirectURL).convert()
}

func signIn(loginId: String, uri: String?) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkSignIn(loginId: loginId, uri: uri).convert()
func signIn(loginId: String, redirectURL: String?, options: [SignInOptions]) async throws -> EnchantedLinkResponse {
let (refreshJwt, loginOptions) = try options.convert()
return try await client.enchantedLinkSignIn(loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: loginOptions).convert()
}

func signUpOrIn(loginId: String, uri: String?) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkSignUpOrIn(loginId: loginId, uri: uri).convert()
func signUpOrIn(loginId: String, redirectURL: String?, options: [SignInOptions]) async throws -> EnchantedLinkResponse {
let (refreshJwt, loginOptions) = try options.convert()
return try await client.enchantedLinkSignUpOrIn(loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: loginOptions).convert()
}

func updateEmail(_ email: String, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkUpdateEmail(email, loginId: loginId, uri: uri, refreshJwt: refreshJwt, options: options).convert()
func updateEmail(_ email: String, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> EnchantedLinkResponse {
return try await client.enchantedLinkUpdateEmail(email, loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: options).convert()
}

func checkForSession(pendingRef: String) async throws -> AuthenticationResponse {
Expand Down
22 changes: 12 additions & 10 deletions src/internal/routes/MagicLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@ class MagicLink: DescopeMagicLink {
self.client = client
}

func signUp(with method: DeliveryMethod, loginId: String, details: SignUpDetails?, uri: String?) async throws -> String {
return try await client.magicLinkSignUp(with: method, loginId: loginId, details: details, uri: uri).convert(method: method)
func signUp(with method: DeliveryMethod, loginId: String, details: SignUpDetails?, redirectURL: String?) async throws -> String {
return try await client.magicLinkSignUp(with: method, loginId: loginId, details: details, redirectURL: redirectURL).convert(method: method)
}

func signIn(with method: DeliveryMethod, loginId: String, uri: String?) async throws -> String {
return try await client.magicLinkSignIn(with: method, loginId: loginId, uri: uri).convert(method: method)
func signIn(with method: DeliveryMethod, loginId: String, redirectURL: String?, options: [SignInOptions]) async throws -> String {
let (refreshJwt, loginOptions) = try options.convert()
return try await client.magicLinkSignIn(with: method, loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: loginOptions).convert(method: method)
}

func signUpOrIn(with method: DeliveryMethod, loginId: String, uri: String?) async throws -> String {
return try await client.magicLinkSignUpOrIn(with: method, loginId: loginId, uri: uri).convert(method: method)
func signUpOrIn(with method: DeliveryMethod, loginId: String, redirectURL: String?, options: [SignInOptions]) async throws -> String {
let (refreshJwt, loginOptions) = try options.convert()
return try await client.magicLinkSignUpOrIn(with: method, loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: loginOptions).convert(method: method)
}

func updateEmail(_ email: String, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> String {
return try await client.magicLinkUpdateEmail(email, loginId: loginId, uri: uri, refreshJwt: refreshJwt, options: options).convert(method: .email)
func updateEmail(_ email: String, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> String {
return try await client.magicLinkUpdateEmail(email, loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: options).convert(method: .email)
}

func updatePhone(_ phone: String, with method: DeliveryMethod, loginId: String, uri: String?, refreshJwt: String, options: UpdateOptions) async throws -> String {
return try await client.magicLinkUpdatePhone(phone, with: method, loginId: loginId, uri: uri, refreshJwt: refreshJwt, options: options).convert(method: method)
func updatePhone(_ phone: String, with method: DeliveryMethod, loginId: String, redirectURL: String?, refreshJwt: String, options: UpdateOptions) async throws -> String {
return try await client.magicLinkUpdatePhone(phone, with: method, loginId: loginId, redirectURL: redirectURL, refreshJwt: refreshJwt, options: options).convert(method: method)
}

func verify(token: String) async throws -> AuthenticationResponse {
Expand Down
6 changes: 4 additions & 2 deletions src/internal/routes/OAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ class OAuth: DescopeOAuth {
self.client = client
}

func start(provider: OAuthProvider, redirectURL: String?) async throws -> String {
return try await client.oauthStart(provider: provider, redirectURL: redirectURL).url
func start(provider: OAuthProvider, redirectURL: String?, options: [SignInOptions]) async throws -> String {
let (refreshJwt, loginOptions) = try options.convert()
let response = try await client.oauthStart(provider: provider, redirectURL: redirectURL, refreshJwt: refreshJwt, options: loginOptions)
return response.url
}

func exchange(code: String) async throws -> AuthenticationResponse {
Expand Down
Loading