Clone the twdehands SDK into mrktplaats and retarget naming and defaults for app.marktplaats.nl while keeping the same request/response bodies and endpoint behavior.
116 lines
3.6 KiB
Go
116 lines
3.6 KiB
Go
package mrktplaats
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// AuthService handles login and two-factor authentication.
|
|
type AuthService struct {
|
|
t *transport
|
|
}
|
|
|
|
// LoginRequest is the payload for initiating a login.
|
|
type LoginRequest struct {
|
|
Email string `json:"email"`
|
|
Password string `json:"password"`
|
|
Type string `json:"type"`
|
|
VerificationParameters verificationParameters `json:"verificationParameters"`
|
|
}
|
|
|
|
type verificationParameters struct {
|
|
MobileTokenForSMS *string `json:"mobileTokenForSms"`
|
|
}
|
|
|
|
// LoginResponse is returned from a login attempt. If 2FA is required,
|
|
// Verification is populated. If login succeeds immediately, Auth is populated.
|
|
type LoginResponse struct {
|
|
Verification *Verification `json:"verification,omitempty"`
|
|
Auth *AuthToken `json:"auth,omitempty"`
|
|
User *User `json:"user,omitempty"`
|
|
}
|
|
|
|
// Verification contains the 2FA challenge details.
|
|
type Verification struct {
|
|
RequestID string `json:"requestId"`
|
|
Method string `json:"method"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// AuthToken contains the access and refresh tokens.
|
|
type AuthToken struct {
|
|
AccessToken string `json:"accessToken"`
|
|
RefreshToken string `json:"refreshToken"`
|
|
ExpiresIn string `json:"expiresIn"`
|
|
}
|
|
|
|
// AuthResponse is the full response after successful authentication.
|
|
type AuthResponse struct {
|
|
Auth AuthToken `json:"auth"`
|
|
User User `json:"user"`
|
|
}
|
|
|
|
// Login initiates authentication with email and password.
|
|
// If 2FA is required, the response contains a Verification with a RequestID
|
|
// that must be passed to VerifyCode.
|
|
func (s *AuthService) Login(ctx context.Context, email, password string) (*LoginResponse, error) {
|
|
body := LoginRequest{
|
|
Email: email,
|
|
Password: password,
|
|
Type: "user-credentials",
|
|
VerificationParameters: verificationParameters{MobileTokenForSMS: nil},
|
|
}
|
|
|
|
var resp LoginResponse
|
|
if err := s.t.postJSON(ctx, "/app/identity/v3/login", nil, nil, body, &resp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.Auth != nil {
|
|
s.t.setAccessToken(resp.Auth.AccessToken)
|
|
}
|
|
return &resp, nil
|
|
}
|
|
|
|
// RefreshToken exchanges a refresh token for a new access token without requiring
|
|
// the user to re-enter their credentials. The response contains a fresh AuthToken
|
|
// with a new accessToken, refreshToken, and expiresIn.
|
|
func (s *AuthService) RefreshToken(ctx context.Context, refreshToken string) (*AuthToken, error) {
|
|
body := struct {
|
|
RefreshToken string `json:"refreshToken"`
|
|
}{RefreshToken: refreshToken}
|
|
|
|
var resp struct {
|
|
Auth AuthToken `json:"auth"`
|
|
}
|
|
if err := s.t.postJSON(ctx, "/app/identity/v3/refreshtoken", nil, nil, body, &resp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.t.setAccessToken(resp.Auth.AccessToken)
|
|
return &resp.Auth, nil
|
|
}
|
|
|
|
// VerifyCode completes 2FA by submitting the SMS verification code.
|
|
// On success the access token is automatically set on the client.
|
|
func (s *AuthService) VerifyCode(ctx context.Context, requestID, code string) (*AuthResponse, error) {
|
|
path := fmt.Sprintf("/app/identity/v3/two-factor-auth/verification/requests/%s/verify-code", requestID)
|
|
|
|
body := struct {
|
|
Key *string `json:"key"`
|
|
MagicToken *string `json:"magicToken"`
|
|
VerificationCode string `json:"verificationCode"`
|
|
VerificationParameters verificationParameters `json:"verificationParameters"`
|
|
}{
|
|
VerificationCode: code,
|
|
}
|
|
|
|
var resp AuthResponse
|
|
if err := s.t.postJSON(ctx, path, nil, nil, body, &resp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.t.setAccessToken(resp.Auth.AccessToken)
|
|
return &resp, nil
|
|
}
|