Skip to content

Commit f42896b

Browse files
committed
add new token endpoint
1 parent 898bcd2 commit f42896b

File tree

4 files changed

+127
-49
lines changed

4 files changed

+127
-49
lines changed

backend/app/routers/keycloak.py

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
retreive_refresh_token,
1212
)
1313
from app.models.tokens import TokenDB
14-
from app.models.users import UserDB, UserLogin
15-
from app.routers.utils import save_refresh_token
14+
from app.models.users import UserLogin
15+
from app.routers.utils import save_refresh_token, get_token
1616
from fastapi import APIRouter, HTTPException, Security
1717
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
1818
from jose import ExpiredSignatureError, JWTError, jwt
@@ -107,56 +107,10 @@ async def loginPost(userIn: UserLogin):
107107
async def auth(code: str) -> RedirectResponse:
108108
"""Redirect endpoint Keycloak redirects to after login."""
109109
logger.info("In /api/v2/auth")
110-
# get token from Keycloak
111-
token_body = keycloak_openid.token(
112-
grant_type="authorization_code",
113-
code=code,
114-
redirect_uri=settings.auth_redirect_uri,
115-
)
116110

111+
token_body = await get_token(code)
117112
access_token = token_body["access_token"]
118113

119-
# create user in db if it doesn't already exist; get the user_id
120-
userinfo = keycloak_openid.userinfo(access_token)
121-
keycloak_id = userinfo["sub"]
122-
given_name = userinfo.get("given_name", " ")
123-
family_name = userinfo.get("family_name", " ")
124-
email = userinfo["email"]
125-
126-
# check if this is the 1st user, make it admin
127-
count = await UserDB.count()
128-
129-
if count == 0:
130-
user = UserDB(
131-
email=email,
132-
first_name=given_name,
133-
last_name=family_name,
134-
hashed_password="",
135-
keycloak_id=keycloak_id,
136-
admin=True,
137-
)
138-
else:
139-
user = UserDB(
140-
email=email,
141-
first_name=given_name,
142-
last_name=family_name,
143-
hashed_password="",
144-
keycloak_id=keycloak_id,
145-
admin=False,
146-
)
147-
matched_user = await UserDB.find_one(UserDB.email == email)
148-
if matched_user is None:
149-
await user.insert()
150-
151-
# store/update refresh token and link to that userid
152-
token_exist = await TokenDB.find_one(TokenDB.email == email)
153-
if token_exist is not None:
154-
token_exist.refresh_token = token_body["refresh_token"]
155-
await token_exist.save()
156-
else:
157-
token_created = TokenDB(email=email, refresh_token=token_body["refresh_token"])
158-
await token_created.insert()
159-
160114
# redirect to frontend
161115
auth_url = f"{settings.frontend_url}/auth"
162116

@@ -168,6 +122,11 @@ async def auth(code: str) -> RedirectResponse:
168122
return response
169123

170124

125+
@router.get("/token")
126+
async def token(code: str):
127+
return await get_token(code)
128+
129+
171130
@router.get("/refresh_token")
172131
async def refresh_token(
173132
credentials: HTTPAuthorizationCredentials = Security(security),

backend/app/routers/utils.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import mimetypes
22
from typing import Optional
33

4+
from app.config import settings
5+
from app.keycloak_auth import keycloak_openid
46
from app.models.files import ContentType
57
from app.models.tokens import TokenDB
8+
from app.models.users import UserDB
69

710

811
def get_content_type(
@@ -35,3 +38,58 @@ async def save_refresh_token(refresh_token: str, email: str):
3538
else:
3639
token_created = TokenDB(email=email, refresh_token=refresh_token)
3740
await token_created.insert()
41+
42+
43+
async def get_token(code: str):
44+
# get token from Keycloak
45+
token_body = keycloak_openid.token(
46+
grant_type="authorization_code",
47+
code=code,
48+
redirect_uri=settings.auth_redirect_uri,
49+
)
50+
51+
access_token = token_body["access_token"]
52+
refresh_token = token_body["refresh_token"]
53+
54+
# create user in db if it doesn't already exist; get the user_id
55+
userinfo = keycloak_openid.userinfo(access_token)
56+
keycloak_id = userinfo["sub"]
57+
given_name = userinfo.get("given_name", " ")
58+
family_name = userinfo.get("family_name", " ")
59+
email = userinfo["email"]
60+
61+
# check if this is the 1st user, make it admin
62+
count = await UserDB.count()
63+
64+
if count == 0:
65+
user = UserDB(
66+
email=email,
67+
first_name=given_name,
68+
last_name=family_name,
69+
hashed_password="",
70+
keycloak_id=keycloak_id,
71+
admin=True,
72+
)
73+
else:
74+
user = UserDB(
75+
email=email,
76+
first_name=given_name,
77+
last_name=family_name,
78+
hashed_password="",
79+
keycloak_id=keycloak_id,
80+
admin=False,
81+
)
82+
matched_user = await UserDB.find_one(UserDB.email == email)
83+
if matched_user is None:
84+
await user.insert()
85+
86+
# store/update refresh token and link to that userid
87+
token_exist = await TokenDB.find_one(TokenDB.email == email)
88+
if token_exist is not None:
89+
token_exist.refresh_token = refresh_token
90+
await token_exist.save()
91+
else:
92+
token_created = TokenDB(email=email, refresh_token=refresh_token)
93+
await token_created.insert()
94+
95+
return token_body

frontend/src/openapi/v2/services/AuthService.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,27 @@ export class AuthService {
8888
});
8989
}
9090

91+
/**
92+
* Token
93+
* @param code
94+
* @returns any Successful Response
95+
* @throws ApiError
96+
*/
97+
public static tokenApiV2AuthTokenGet(
98+
code: string,
99+
): CancelablePromise<any> {
100+
return __request({
101+
method: 'GET',
102+
path: `/api/v2/auth/token`,
103+
query: {
104+
'code': code,
105+
},
106+
errors: {
107+
422: `Validation Error`,
108+
},
109+
});
110+
}
111+
91112
/**
92113
* Refresh Token
93114
* @returns any Successful Response

openapi.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12058,6 +12058,46 @@
1205812058
}
1205912059
}
1206012060
},
12061+
"/api/v2/auth/token": {
12062+
"get": {
12063+
"tags": [
12064+
"auth"
12065+
],
12066+
"summary": "Token",
12067+
"operationId": "token_api_v2_auth_token_get",
12068+
"parameters": [
12069+
{
12070+
"required": true,
12071+
"schema": {
12072+
"title": "Code",
12073+
"type": "string"
12074+
},
12075+
"name": "code",
12076+
"in": "query"
12077+
}
12078+
],
12079+
"responses": {
12080+
"200": {
12081+
"description": "Successful Response",
12082+
"content": {
12083+
"application/json": {
12084+
"schema": {}
12085+
}
12086+
}
12087+
},
12088+
"422": {
12089+
"description": "Validation Error",
12090+
"content": {
12091+
"application/json": {
12092+
"schema": {
12093+
"$ref": "#/components/schemas/HTTPValidationError"
12094+
}
12095+
}
12096+
}
12097+
}
12098+
}
12099+
}
12100+
},
1206112101
"/api/v2/auth/refresh_token": {
1206212102
"get": {
1206312103
"tags": [

0 commit comments

Comments
 (0)