Skip to content

Commit 0f77586

Browse files
authored
Merge pull request #142 from oslokommune/remove-cached-credentials
Remove support for file system credentials caching
2 parents 6071043 + 903ea0e commit 0f77586

12 files changed

Lines changed: 42 additions & 298 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## ?.?.? - Unreleased
2+
3+
* Removed support for file system credentials caching.
4+
15
## 4.0.0 - 2026-01-22
26

37
* Added support for Python 3.14.

okdata/sdk/auth/auth.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
)
1010
from okdata.sdk.auth.credentials.password_grant import TokenServiceProvider
1111
from okdata.sdk.exceptions import ApiAuthenticateError
12-
from okdata.sdk.file_cache import FileCache
1312

1413
log = logging.getLogger()
1514

@@ -25,7 +24,15 @@ class Authenticate:
2524
_expires_at = None
2625
_refresh_expires_at = None
2726

27+
# TODO: Remove keyword argument `file_cache` in a later release.
2828
def __init__(self, config, token_provider=None, file_cache=None):
29+
if file_cache is not None:
30+
log.warning(
31+
"Keyword argument `file_cache` to "
32+
"`okdata.sdk.auth.auth.Authenticate` is deprecated and will "
33+
"be removed in a later release of okdata-sdk."
34+
)
35+
2936
self.token_provider = token_provider
3037
if not self.token_provider:
3138
try:
@@ -36,10 +43,6 @@ def __init__(self, config, token_provider=None, file_cache=None):
3643
except StopIteration:
3744
log.info("No valid auth strategies available")
3845

39-
self.file_cache = file_cache
40-
if not self.file_cache:
41-
self.file_cache = FileCache(config)
42-
4346
def _resolve_token_provider(self, config):
4447
# Add more TokenProviders to accept different login methods
4548
strategies = [ClientCredentialsProvider, TokenServiceProvider]
@@ -69,15 +72,6 @@ def login(self, force=False):
6972
if not self.token_provider:
7073
return
7174

72-
cached = self.file_cache.read_credentials()
73-
if cached:
74-
self._access_token = cached["access_token"]
75-
self._refresh_token = cached.get("refresh_token")
76-
if expires_at := cached.get("expires_at"):
77-
self._expires_at = datetime.fromisoformat(expires_at)
78-
if refresh_expires_at := cached.get("refresh_expires_at"):
79-
self._refresh_expires_at = datetime.fromisoformat(refresh_expires_at)
80-
8175
if self._access_token and not _is_expired(self._expires_at):
8276
log.info("Token not expired, skipping")
8377
return
@@ -109,7 +103,6 @@ def refresh_access_token(self):
109103
)
110104

111105
self._access_token = tokens["access_token"]
112-
self.file_cache.write_credentials(credentials=str(self))
113106

114107
def __repr__(self):
115108
return json.dumps(

okdata/sdk/file_cache.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

okdata/sdk/io_utils.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,8 @@
1-
import os
21
import errno
2+
import os
33
from pathlib import Path
44

55

6-
def write_to_okdata_cache(content, filename, failure_count=0):
7-
okdata_cache_path = Path(f"{os.environ['HOME']}/.okdata/cache")
8-
9-
if failure_count == 2:
10-
print(f"Could not write credentials to {okdata_cache_path}/{filename}")
11-
return
12-
13-
if okdata_cache_path.exists():
14-
with open(f"{okdata_cache_path}/{filename}", "w+") as file:
15-
file.write(content)
16-
else:
17-
create_dir(okdata_cache_path)
18-
write_to_okdata_cache(content, filename, failure_count + 1)
19-
20-
216
def create_dir(path):
227
try:
238
os.makedirs(path)
@@ -26,18 +11,6 @@ def create_dir(path):
2611
raise
2712

2813

29-
def read_from_okdata_cache(filename):
30-
okdata_cache_path = Path(f"{os.environ['HOME']}/.okdata/cache")
31-
32-
try:
33-
file = open(f"{okdata_cache_path}/{filename}", "r")
34-
except IOError:
35-
return None
36-
else:
37-
with file:
38-
return file.read()
39-
40-
4114
def write_file_content(file_name, path, content):
4215
if not Path(path).exists():
4316
create_dir(path)

tests/auth/auth_test.py

Lines changed: 10 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
import re
44

55
import pytest
6+
from freezegun import freeze_time
67

78
from okdata.sdk.auth.auth import Authenticate
89
from okdata.sdk.auth.credentials.client_credentials import ClientCredentialsProvider
910
from okdata.sdk.config import Config
1011
from okdata.sdk.exceptions import ApiAuthenticateError
11-
from freezegun import freeze_time
12-
1312
from tests.auth.client_credentials_test_utils import (
14-
expired_time,
15-
from_cache_expired_token,
16-
from_cache_not_expired_token,
17-
not_expired_time,
13+
not_expired_token,
1814
utc_now,
1915
)
2016
from tests.test_utils import (
@@ -29,33 +25,12 @@
2925
token_endpoint = "https://login.oslo.kommune.no/auth/realms/api-catalog/protocol/openid-connect/token"
3026

3127

32-
@pytest.fixture(scope="function")
33-
def mock_home_dir(monkeypatch, tmp_path):
34-
monkeypatch.setenv("HOME", str(tmp_path))
35-
36-
3728
@freeze_time(utc_now)
3829
class TestAuthenticate:
39-
def test_authenticate_cache_disabled(self, requests_mock, mock_home_dir):
40-
client_credentials_provider = ClientCredentialsProvider(config)
41-
auth = Authenticate(config=config, token_provider=client_credentials_provider)
42-
43-
auth.file_cache.credentials_cache_enabled = False
44-
45-
response = json.dumps(client_credentials_response)
46-
matcher = re.compile(token_endpoint)
47-
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
48-
49-
auth.login()
50-
assert auth._access_token == client_credentials_response["access_token"]
51-
assert auth._refresh_token == client_credentials_response["refresh_token"]
52-
53-
def test_authenticat_no_cache(self, requests_mock, mock_home_dir):
30+
def test_authenticate(self, requests_mock):
5431
client_credentials_provider = ClientCredentialsProvider(config)
5532
auth = Authenticate(config=config, token_provider=client_credentials_provider)
5633

57-
auth.file_cache.credentials_cache_enabled = True
58-
5934
response = json.dumps(client_credentials_response)
6035
matcher = re.compile(token_endpoint)
6136
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
@@ -64,99 +39,19 @@ def test_authenticat_no_cache(self, requests_mock, mock_home_dir):
6439
assert auth._access_token == client_credentials_response["access_token"]
6540
assert auth._refresh_token == client_credentials_response["refresh_token"]
6641

67-
def test_authenticate_cached_credentials(self, mock_home_dir):
68-
client_credentials_provider = ClientCredentialsProvider(config)
69-
auth = Authenticate(config=config, token_provider=client_credentials_provider)
70-
71-
auth.file_cache.credentials_cache_enabled = True
72-
cached_credentials = {
73-
"provider": "ClientCredentialsProvider",
74-
"access_token": from_cache_not_expired_token,
75-
"refresh_token": from_cache_not_expired_token,
76-
"expires_at": not_expired_time.isoformat(),
77-
"refresh_expires_at": not_expired_time.isoformat(),
78-
}
79-
80-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
81-
auth.login()
82-
assert auth._access_token == cached_credentials["access_token"]
83-
assert auth._refresh_token == cached_credentials["refresh_token"]
84-
85-
def test_authenticate_refresh_credentials(self, requests_mock, mock_home_dir):
42+
def test_authenticate_refresh_credentials(self, requests_mock):
8643
client_credentials_provider = ClientCredentialsProvider(config)
8744
auth = Authenticate(config=config, token_provider=client_credentials_provider)
8845

89-
auth.file_cache.credentials_cache_enabled = True
90-
91-
cached_credentials = {
92-
"provider": "ClientCredentialsProvider",
93-
"access_token": from_cache_not_expired_token,
94-
"refresh_token": from_cache_not_expired_token,
95-
"expires_at": not_expired_time.isoformat(),
96-
"refresh_expires_at": not_expired_time.isoformat(),
97-
}
98-
99-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
100-
10146
response = json.dumps(client_credentials_response)
10247
matcher = re.compile(token_endpoint)
10348
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
10449

10550
auth.login()
106-
assert auth._access_token == cached_credentials["access_token"]
107-
assert auth._refresh_token == cached_credentials["refresh_token"]
108-
109-
def test_authenticate_expired_tokens(self, requests_mock, mock_home_dir):
110-
client_credentials_provider = ClientCredentialsProvider(config)
111-
auth = Authenticate(config=config, token_provider=client_credentials_provider)
112-
113-
auth.file_cache.credentials_cache_enabled = True
114-
115-
cached_credentials = {
116-
"provider": "TokenServiceProvider",
117-
"access_token": from_cache_expired_token,
118-
"refresh_token": from_cache_expired_token,
119-
"expires_at": expired_time.isoformat(),
120-
"refresh_expires_at": expired_time.isoformat(),
121-
}
51+
assert auth._access_token == not_expired_token
52+
assert auth._refresh_token == not_expired_token
12253

123-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
124-
125-
response = json.dumps(client_credentials_response)
126-
matcher = re.compile(token_endpoint)
127-
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
128-
129-
auth.login()
130-
print(from_cache_not_expired_token)
131-
print(from_cache_expired_token)
132-
assert auth._access_token == client_credentials_response["access_token"]
133-
assert auth._refresh_token == client_credentials_response["access_token"]
134-
135-
def test_authenticate_expired_access_token(self, requests_mock, mock_home_dir):
136-
client_credentials_provider = ClientCredentialsProvider(config)
137-
auth = Authenticate(config=config, token_provider=client_credentials_provider)
138-
139-
auth.file_cache.credentials_cache_enabled = True
140-
141-
cached_credentials = {
142-
"provider": "TokenServiceProvider",
143-
"access_token": from_cache_expired_token,
144-
"refresh_token": from_cache_not_expired_token,
145-
"expires_at": expired_time.isoformat(),
146-
"refresh_expires_at": not_expired_time.isoformat(),
147-
}
148-
149-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
150-
151-
response = json.dumps(client_credentials_response)
152-
matcher = re.compile(token_endpoint)
153-
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
154-
155-
auth.login()
156-
assert auth._access_token == from_cache_not_expired_token
157-
assert auth._refresh_token == cached_credentials["refresh_token"]
158-
159-
def test_authenticate_fail(self, requests_mock, mock_home_dir):
54+
def test_authenticate_fail(self, requests_mock):
16055
client_credentials_provider = ClientCredentialsProvider(
16156
config, client_id="wrong_id"
16257
)
@@ -168,63 +63,18 @@ def test_authenticate_fail(self, requests_mock, mock_home_dir):
16863
matcher = re.compile(token_endpoint)
16964
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
17065

171-
try:
66+
with pytest.raises(ApiAuthenticateError):
17267
auth.login()
173-
except ApiAuthenticateError:
174-
assert True
17568

176-
def test_refresh_inactive_session(self, requests_mock, mock_home_dir):
69+
def test_refresh_no_refresh_token(self, requests_mock):
17770
client_credentials_provider = ClientCredentialsProvider(config)
17871
auth = Authenticate(config=config, token_provider=client_credentials_provider)
17972

180-
auth.file_cache.credentials_cache_enabled = True
181-
182-
cached_credentials = {
183-
"provider": "TokenServiceProvider",
184-
"access_token": from_cache_expired_token,
185-
"refresh_token": from_cache_not_expired_token,
186-
"expires_at": expired_time.isoformat(),
187-
"refresh_expires_at": not_expired_time.isoformat(),
188-
}
189-
190-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
191-
192-
error_msg = {
193-
"error": "invalid_grant",
194-
"error_description": "Session not active",
195-
}
196-
refresh_response = {"text": json.dumps(error_msg), "status_code": 400}
197-
login_response = {
198-
"text": json.dumps(client_credentials_response),
199-
"status_code": 200,
200-
}
201-
matcher = re.compile(token_endpoint)
202-
requests_mock.register_uri("POST", matcher, [refresh_response, login_response])
203-
204-
auth.login()
205-
206-
assert auth._access_token == from_cache_not_expired_token
207-
assert auth._refresh_token == cached_credentials["refresh_token"]
208-
209-
def test_refresh_no_refresh_token(self, requests_mock, mock_home_dir):
210-
client_credentials_provider = ClientCredentialsProvider(config)
211-
auth = Authenticate(config=config, token_provider=client_credentials_provider)
212-
213-
auth.file_cache.credentials_cache_enabled = True
214-
215-
cached_credentials = {
216-
"provider": "TokenServiceProvider",
217-
"access_token": from_cache_expired_token,
218-
"expires_at": expired_time.isoformat(),
219-
}
220-
221-
auth.file_cache.write_credentials(json.dumps(cached_credentials))
222-
22373
response = json.dumps(client_credentials_response_no_refresh)
22474
matcher = re.compile(token_endpoint)
22575
requests_mock.register_uri("POST", matcher, text=response, status_code=200)
22676

22777
auth.login()
22878

229-
assert auth._access_token == from_cache_not_expired_token
79+
assert auth._access_token == not_expired_token
23080
assert auth._refresh_token is None

0 commit comments

Comments
 (0)