Files
Joren 25410749db Initial Marktplaats SDK scaffold
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.
2026-04-15 23:45:49 +02:00

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
}