or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-utilities.mdfull-refresh-streams.mdincremental-streams.mdindex.mdoauth-authentication.mdsource-configuration.md

oauth-authentication.mddocs/

0

# OAuth2 Authentication

1

2

OAuth2 authentication implementation for the Airbyte Source Xero connector. This module handles secure authentication with Xero's API, including automatic token refresh, rate limiting, and error handling.

3

4

## Core Imports

5

6

```python

7

import base64

8

import logging

9

from typing import Any, Mapping

10

import backoff

11

import requests

12

from airbyte_cdk.sources.streams.http.exceptions import DefaultBackoffException

13

from airbyte_cdk.sources.streams.http.requests_native_auth import SingleUseRefreshTokenOauth2Authenticator

14

```

15

16

## Capabilities

17

18

### Xero OAuth2 Authenticator

19

20

Custom OAuth2 authenticator that extends Airbyte CDK's standard OAuth2 implementation with Xero-specific requirements for token refresh and authentication headers.

21

22

```python { .api }

23

class XeroSingleUseRefreshTokenOauth2Authenticator(SingleUseRefreshTokenOauth2Authenticator):

24

"""

25

OAuth2 authenticator for Xero API with custom token refresh handling.

26

27

Inherits from airbyte_cdk SingleUseRefreshTokenOauth2Authenticator and

28

implements Xero-specific authentication patterns including Basic Auth

29

headers for token refresh and specialized retry logic.

30

"""

31

32

def build_refresh_request_body(self) -> Mapping[str, Any]:

33

"""

34

Build request body for OAuth2 token refresh.

35

36

Removes client_id and client_secret from request body as Xero

37

requires these in the Authorization header instead.

38

39

Returns:

40

Request body mapping without client credentials

41

"""

42

43

def build_refresh_request_headers(self) -> Mapping[str, Any]:

44

"""

45

Build request headers for OAuth2 token refresh.

46

47

Creates Basic Authentication header using client_id and client_secret

48

as required by Xero's OAuth2 implementation.

49

50

Returns:

51

Headers mapping with Authorization header containing Basic auth credentials

52

"""

53

54

def _get_refresh_access_token_response(self):

55

"""

56

Execute token refresh request with Xero-specific retry logic.

57

58

Implements backoff and retry for 429 (rate limiting) and 500+

59

(server error) status codes with exponential backoff strategy.

60

61

Returns:

62

JSON response from token refresh endpoint

63

64

Raises:

65

requests.exceptions.RequestException: For unrecoverable HTTP errors

66

"""

67

```

68

69

## Authentication Flow

70

71

### Token Refresh Process

72

73

The Xero OAuth2 flow follows these steps:

74

75

1. **Initial Authentication**: Uses provided access_token and refresh_token

76

2. **Token Validation**: Checks token expiry before API requests

77

3. **Automatic Refresh**: Refreshes expired tokens using refresh_token

78

4. **Retry Logic**: Handles rate limiting and server errors during refresh

79

5. **Header Management**: Applies proper authentication headers to API requests

80

81

### Request Authentication

82

83

```python { .api }

84

# The authenticator automatically handles:

85

AuthenticationHeaders = {

86

"Authorization": "Bearer {access_token}", # OAuth2 bearer token

87

"Xero-Tenant-Id": "{tenant_id}", # Required for all Xero API calls

88

"Accept": "application/json", # Content type specification

89

"User-Agent": "Airbyte/{version}" # Client identification

90

}

91

```

92

93

## Usage Examples

94

95

### Manual Authenticator Creation

96

97

```python

98

from source_xero.oauth import XeroSingleUseRefreshTokenOauth2Authenticator

99

100

# Configuration with OAuth2 credentials

101

config = {

102

"authentication": {

103

"client_id": "your-xero-client-id",

104

"client_secret": "your-xero-client-secret",

105

"refresh_token": "your-refresh-token",

106

"access_token": "current-access-token",

107

"token_expiry_date": "2024-12-31T23:59:59Z"

108

},

109

"tenant_id": "your-xero-tenant-id"

110

}

111

112

# Create authenticator instance

113

authenticator = XeroSingleUseRefreshTokenOauth2Authenticator(

114

connector_config=config,

115

token_refresh_endpoint="https://identity.xero.com/connect/token",

116

client_id=config["authentication"]["client_id"],

117

client_secret=config["authentication"]["client_secret"],

118

access_token_config_path=["authentication", "access_token"],

119

refresh_token_config_path=["authentication", "refresh_token"],

120

token_expiry_date_config_path=["authentication", "token_expiry_date"]

121

)

122

```

123

124

### Integration with HTTP Requests

125

126

```python

127

import requests

128

129

# The authenticator can be used with any HTTP client

130

session = requests.Session()

131

132

# Apply authentication to request

133

authenticated_request = authenticator.apply(

134

session.prepare_request(

135

requests.Request("GET", "https://api.xero.com/api.xro/2.0/Accounts")

136

)

137

)

138

139

# Execute authenticated request

140

response = session.send(authenticated_request)

141

```

142

143

### Token Refresh Handling

144

145

```python

146

# Token refresh is handled automatically, but you can monitor it:

147

try:

148

# This will automatically refresh token if needed

149

response = authenticator._get_refresh_access_token_response()

150

print("Token refreshed successfully")

151

except requests.exceptions.RequestException as e:

152

print(f"Token refresh failed: {e}")

153

```

154

155

## Error Handling

156

157

### Rate Limiting (429 Responses)

158

159

The authenticator implements exponential backoff for rate limiting:

160

161

```python

162

# Automatic retry with backoff for rate limiting

163

# - Initial delay: 1 second

164

# - Maximum retries: 3 attempts

165

# - Backoff multiplier: 2x

166

# - Maximum delay: 60 seconds

167

```

168

169

### Server Errors (500+ Responses)

170

171

Server errors are handled with retry logic:

172

173

```python

174

# Retry for server errors (500, 502, 503, 504)

175

# - Same backoff strategy as rate limiting

176

# - Distinguishes between client (4xx) and server (5xx) errors

177

# - Only retries recoverable server errors

178

```

179

180

### Authentication Errors (401 Responses)

181

182

```python

183

# Token expiry and invalid credentials handling:

184

# - Automatic token refresh on 401 responses

185

# - Fallback to refresh_token if access_token is invalid

186

# - Error reporting for invalid refresh_token

187

```

188

189

## Security Considerations

190

191

### Credential Management

192

193

- **Client Secrets**: Never logged or exposed in error messages

194

- **Tokens**: Stored securely and rotated automatically

195

- **Refresh Tokens**: Single-use pattern prevents token replay attacks

196

- **HTTPS Only**: All authentication requests use secure HTTPS

197

198

### Token Storage

199

200

```python

201

# Secure token handling practices:

202

TokenSecurity = {

203

"access_token": "Treated as secret, never logged",

204

"refresh_token": "Single-use, invalidated after refresh",

205

"client_secret": "Never included in request bodies",

206

"token_expiry": "Validated before each request"

207

}

208

```

209

210

## Xero API Requirements

211

212

### OAuth2 Configuration

213

214

To use this authenticator, you need:

215

216

1. **Xero Developer Account**: Register at https://developer.xero.com

217

2. **Custom Connection**: Create a custom connection (production) or demo company (testing)

218

3. **OAuth2 App**: Configure OAuth2 application with appropriate scopes

219

4. **Credentials**: Obtain client_id, client_secret, and initial tokens

220

221

### Required Scopes

222

223

The connector requires these OAuth2 scopes for full functionality:

224

225

```python

226

RequiredScopes = [

227

"accounting.transactions", # Access to financial transactions

228

"accounting.contacts", # Access to contact information

229

"accounting.settings", # Access to account settings

230

"accounting.attachments" # Access to document attachments

231

]

232

```

233

234

### API Limitations

235

236

- **Rate Limits**: 60 API calls per minute per tenant

237

- **Token Lifetime**: Access tokens expire after 30 minutes

238

- **Refresh Tokens**: Single-use, must be stored after each refresh

239

- **Tenant Scope**: Each token set is limited to one Xero organization