Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
aisbf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
aisbf
Commits
a3b0269d
Commit
a3b0269d
authored
Apr 21, 2026
by
Your Name
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix missing expires_at field in database-saved Claude credentials
parent
7b1132e4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
116 additions
and
13 deletions
+116
-13
claude.py
aisbf/auth/claude.py
+7
-7
claude.py
aisbf/providers/claude.py
+6
-2
main.py
main.py
+103
-4
No files found.
aisbf/auth/claude.py
View file @
a3b0269d
...
...
@@ -152,12 +152,18 @@ class ClaudeAuth:
- If save_callback is provided, use it (database save for user providers)
- Otherwise, save to file with file locking to prevent race conditions
"""
# Normalize and prepare token data
self
.
tokens
=
data
# Store id_token if received (contains account info)
if
'id_token'
in
data
:
self
.
tokens
[
'id_token'
]
=
data
[
'id_token'
]
# Add local expiry timestamp for easier checking - DO THIS FOR BOTH FILE AND DB USERS!
self
.
tokens
[
'expires_at'
]
=
time
.
time
()
+
data
.
get
(
'expires_in'
,
3600
)
if
self
.
_save_callback
:
# User provider: ONLY use callback, NO file fallback EVER
try
:
self
.
_save_callback
({
'tokens'
:
data
})
self
.
_save_callback
({
'tokens'
:
self
.
tokens
})
logger
.
info
(
"ClaudeAuth: Saved credentials via callback"
)
return
except
Exception
as
e
:
...
...
@@ -167,12 +173,6 @@ class ClaudeAuth:
# Admin/global provider ONLY: save to file
try
:
self
.
tokens
=
data
# Store id_token if received (contains account info)
if
'id_token'
in
data
:
self
.
tokens
[
'id_token'
]
=
data
[
'id_token'
]
# Add local expiry timestamp for easier checking
self
.
tokens
[
'expires_at'
]
=
time
.
time
()
+
data
.
get
(
'expires_in'
,
3600
)
# Ensure directory exists
self
.
credentials_file
.
parent
.
mkdir
(
parents
=
True
,
exist_ok
=
True
)
...
...
aisbf/providers/claude.py
View file @
a3b0269d
...
...
@@ -132,8 +132,12 @@ class ClaudeProviderHandler(BaseProviderHandler):
skip_initial_load
=
True
,
save_callback
=
lambda
creds
:
self
.
_save_auth_to_db
(
creds
)
)
# Set tokens directly from database
auth
.
tokens
=
db_creds
[
'credentials'
]
.
get
(
'tokens'
,
{})
# Set tokens directly from database
auth
.
tokens
=
db_creds
[
'credentials'
]
.
get
(
'tokens'
,
{})
# Add expires_at if missing (for existing credentials saved before fix)
if
auth
.
tokens
and
'expires_at'
not
in
auth
.
tokens
and
'expires_in'
in
auth
.
tokens
:
import
time
auth
.
tokens
[
'expires_at'
]
=
time
.
time
()
+
auth
.
tokens
.
get
(
'expires_in'
,
3600
)
import
logging
logging
.
getLogger
(
__name__
)
.
info
(
f
"ClaudeProviderHandler: Loaded credentials from database for user {self.user_id}"
)
return
auth
...
...
main.py
View file @
a3b0269d
...
...
@@ -6217,7 +6217,34 @@ async def dashboard_provider_auth_check(request: Request, provider_name: str):
claude_config
=
provider_config
.
get
(
'claude_config'
,
{})
else
:
claude_config
=
provider_config
.
claude_config
or
{}
auth
=
ClaudeAuth
(
credentials_file
=
claude_config
.
get
(
'credentials_file'
,
'~/.claude_credentials.json'
))
if
current_user_id
is
None
:
# Admin user: load from file
auth
=
ClaudeAuth
(
credentials_file
=
claude_config
.
get
(
'credentials_file'
,
'~/.claude_credentials.json'
))
else
:
# Regular user: load from database
auth
=
ClaudeAuth
(
credentials_file
=
claude_config
.
get
(
'credentials_file'
,
'~/.claude_credentials.json'
),
skip_initial_load
=
True
)
# Load credentials from database
try
:
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
if
db
:
db_creds
=
db
.
get_user_oauth2_credentials
(
user_id
=
current_user_id
,
provider_id
=
provider_name
,
auth_type
=
'claude_oauth2'
)
if
db_creds
and
db_creds
.
get
(
'credentials'
):
auth
.
tokens
=
db_creds
[
'credentials'
]
.
get
(
'tokens'
,
{})
# Add expires_at if missing (for existing credentials saved before fix)
if
auth
.
tokens
and
'expires_at'
not
in
auth
.
tokens
and
'expires_in'
in
auth
.
tokens
:
auth
.
tokens
[
'expires_at'
]
=
time
.
time
()
+
auth
.
tokens
.
get
(
'expires_in'
,
3600
)
except
Exception
as
e
:
logger
.
warning
(
f
"Failed to load Claude credentials from database: {e}"
)
is_auth
=
auth
.
is_authenticated
()
result
=
{
"authenticated"
:
is_auth
}
if
is_auth
and
auth
.
tokens
and
'expires_at'
in
auth
.
tokens
:
...
...
@@ -6231,7 +6258,31 @@ async def dashboard_provider_auth_check(request: Request, provider_name: str):
kilo_config
=
provider_config
.
get
(
'kilo_config'
,
{})
else
:
kilo_config
=
provider_config
.
kilo_config
or
{}
auth
=
KiloOAuth2
(
credentials_file
=
kilo_config
.
get
(
'credentials_file'
,
'~/.kilo_credentials.json'
))
if
current_user_id
is
None
:
# Admin user: load from file
auth
=
KiloOAuth2
(
credentials_file
=
kilo_config
.
get
(
'credentials_file'
,
'~/.kilo_credentials.json'
))
else
:
# Regular user: load from database
auth
=
KiloOAuth2
(
credentials_file
=
kilo_config
.
get
(
'credentials_file'
,
'~/.kilo_credentials.json'
),
skip_initial_load
=
True
)
# Load credentials from database
try
:
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
if
db
:
db_creds
=
db
.
get_user_oauth2_credentials
(
user_id
=
current_user_id
,
provider_id
=
provider_name
,
auth_type
=
'kilo_oauth2'
)
if
db_creds
and
db_creds
.
get
(
'credentials'
):
auth
.
credentials
=
db_creds
[
'credentials'
]
except
Exception
as
e
:
logger
.
warning
(
f
"Failed to load Kilo credentials from database: {e}"
)
is_auth
=
auth
.
is_authenticated
()
result
=
{
"authenticated"
:
is_auth
}
if
is_auth
and
auth
.
credentials
:
...
...
@@ -6247,7 +6298,31 @@ async def dashboard_provider_auth_check(request: Request, provider_name: str):
qwen_config
=
provider_config
.
get
(
'qwen_config'
,
{})
else
:
qwen_config
=
provider_config
.
qwen_config
or
{}
auth
=
QwenOAuth2
(
credentials_file
=
qwen_config
.
get
(
'credentials_file'
,
'~/.aisbf/qwen_credentials.json'
))
if
current_user_id
is
None
:
# Admin user: load from file
auth
=
QwenOAuth2
(
credentials_file
=
qwen_config
.
get
(
'credentials_file'
,
'~/.aisbf/qwen_credentials.json'
))
else
:
# Regular user: load from database
auth
=
QwenOAuth2
(
credentials_file
=
qwen_config
.
get
(
'credentials_file'
,
'~/.aisbf/qwen_credentials.json'
),
skip_initial_load
=
True
)
# Load credentials from database
try
:
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
if
db
:
db_creds
=
db
.
get_user_oauth2_credentials
(
user_id
=
current_user_id
,
provider_id
=
provider_name
,
auth_type
=
'qwen_oauth2'
)
if
db_creds
and
db_creds
.
get
(
'credentials'
):
auth
.
credentials
=
db_creds
[
'credentials'
]
except
Exception
as
e
:
logger
.
warning
(
f
"Failed to load Qwen credentials from database: {e}"
)
is_auth
=
auth
.
is_authenticated
()
result
=
{
"authenticated"
:
is_auth
}
if
is_auth
and
auth
.
credentials
:
...
...
@@ -6264,7 +6339,31 @@ async def dashboard_provider_auth_check(request: Request, provider_name: str):
codex_config
=
provider_config
.
get
(
'codex_config'
,
{})
else
:
codex_config
=
provider_config
.
codex_config
or
{}
auth
=
CodexOAuth2
(
credentials_file
=
codex_config
.
get
(
'credentials_file'
,
'~/.aisbf/codex_credentials.json'
))
if
current_user_id
is
None
:
# Admin user: load from file
auth
=
CodexOAuth2
(
credentials_file
=
codex_config
.
get
(
'credentials_file'
,
'~/.aisbf/codex_credentials.json'
))
else
:
# Regular user: load from database
auth
=
CodexOAuth2
(
credentials_file
=
codex_config
.
get
(
'credentials_file'
,
'~/.aisbf/codex_credentials.json'
),
skip_initial_load
=
True
)
# Load credentials from database
try
:
from
aisbf.database
import
get_database
db
=
DatabaseRegistry
.
get_config_database
()
if
db
:
db_creds
=
db
.
get_user_oauth2_credentials
(
user_id
=
current_user_id
,
provider_id
=
provider_name
,
auth_type
=
'codex_oauth2'
)
if
db_creds
and
db_creds
.
get
(
'credentials'
):
auth
.
credentials
=
db_creds
[
'credentials'
]
except
Exception
as
e
:
logger
.
warning
(
f
"Failed to load Codex credentials from database: {e}"
)
is_auth
=
auth
.
is_authenticated
()
result
=
{
"authenticated"
:
is_auth
}
if
is_auth
and
auth
.
credentials
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment