Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
SMART
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UNI-KLU
SMART
Commits
9e4844c1
Commit
9e4844c1
authored
Jul 15, 2020
by
Manuel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
restGateway: added security definition to swagger file
parent
eaf5c1f0
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
123 additions
and
46 deletions
+123
-46
swagger.yml
src/rest-gateway/app/configs/swagger.yml
+22
-1
user.py
src/rest-gateway/app/rest/user.py
+8
-45
login_wrapper.py
src/rest-gateway/app/services/login_wrapper.py
+14
-0
token_service.py
src/rest-gateway/app/services/token_service.py
+79
-0
No files found.
src/rest-gateway/app/configs/swagger.yml
View file @
9e4844c1
...
@@ -4,6 +4,13 @@ info:
...
@@ -4,6 +4,13 @@ info:
description
:
This is the documentation for the RESTful API gateway.
description
:
This is the documentation for the RESTful API gateway.
version
:
"
1.0.0"
version
:
"
1.0.0"
securityDefinitions
:
JwtBearerAuth
:
type
:
apiKey
name
:
Authorization
in
:
header
x-apikeyInfoFunc
:
"
services.token_service.verifyToken"
consumes
:
consumes
:
-
"
application/json"
-
"
application/json"
produces
:
produces
:
...
@@ -13,6 +20,20 @@ basePath: "/api"
...
@@ -13,6 +20,20 @@ basePath: "/api"
# Paths supported by the server application
# Paths supported by the server application
paths
:
paths
:
/secret
:
get
:
security
:
-
JwtBearerAuth
:
[]
operationId
:
"
rest.user.secret"
tags
:
-
"
User"
summary
:
"
Testpage
for
authentication"
description
:
"
Should
only
be
accessible
with
a
valid
JWT
token
in
the
'authorization'
header"
responses
:
'
200'
:
description
:
"
OK"
'
401'
:
description
:
"
No
or
an
invalid
token
was
provided"
/tokens/{token}
:
/tokens/{token}
:
post
:
post
:
operationId
:
"
rest.user.verify"
operationId
:
"
rest.user.verify"
...
@@ -155,7 +176,7 @@ definitions:
...
@@ -155,7 +176,7 @@ definitions:
properties
:
properties
:
token
:
token
:
type
:
string
type
:
string
example
:
"
eyJ
hbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.Et9HFtf9R3GEMA0IICOfFMVXY7kkTX1wr4qCyhIf58U
"
example
:
"
eyJ
0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InVzZXJuYW1lQGRvbWFpbi5jb20iLCJjcmVhdGVkX2F0IjoiMjAyMC0wNy0xNSAxNTo0Mzo0OC43MjQ4MjciLCJ2YWxpZF91bnRpbCI6IjIwMjAtMDctMTYgMTU6NDM6NDguNzI0ODI3In0.aR2Xe3pXj_MBS9UJKqhiq4u9M6Bv41ILPaKpA8BVzIY
"
TokenRequest
:
TokenRequest
:
type
:
"
object"
type
:
"
object"
required
:
required
:
...
...
src/rest-gateway/app/rest/user.py
View file @
9e4844c1
# global imports (dont't worry, red is normal)
# global imports (dont't worry, red is normal)
from
db.entities.user
import
User
from
db.entities.user
import
User
from
services.user_service
import
UserService
from
services.user_service
import
UserService
from
services.login_wrapper
import
login_required
from
services.token_service
import
TokenService
from
flask
import
request
,
Response
from
flask
import
request
,
Response
import
bcrypt
import
bcrypt
import
jwt
import
jwt
from
datetime
import
datetime
,
timedelta
def
secret
():
return
"Pineapple does not belong to pizza!"
SIGNING_KEY
=
"yteNrMy6142WKwp8fKfrHkS5nlFpxtHgOXJh1ZPsOrV_gTcsO9eMY7aB7HUzRbTRO9dmZhCl3FdPtuvMe3K8aBA_wc2MmHRo8IkUIGmvUJGsAxKFClN_6oNW5fEvoeVKiL1krA-qjWbR_em-WksePgPoTsySW7QbKdi4f7cwuyK2_JZ2fQj9hDKlfJ2GzMXkKiWcfyCTr30yC6BviAFeRDD_Bpvg6znsrXr53Tq66hnwDwQ6QU7aHVu-bERblKZTYuvkSxsov6yRMEVWQoiuBITsQtIOcgSWK4Dy3BjSbqoIcKw3WG-s3wx1lTen19QbEu8vJC64e0iGeGDWT6vbtg"
TOKEN_VALIDITY_IN_DAYS
=
1
def
generate_token
(
user
:
User
)
->
str
:
'''
creates a JWT token for a user which has the following fields:
- username
- created_at
- valid_until
'''
created_at
=
datetime
.
now
()
valid_until
=
created_at
+
timedelta
(
days
=
1
)
return
jwt
.
encode
(
{
'username'
:
user
.
username
,
'created_at'
:
str
(
created_at
),
'valid_until'
:
str
(
valid_until
),
},
SIGNING_KEY
,
algorithm
=
'HS256'
)
.
decode
(
"utf-8"
)
def
verify
(
token
):
def
verify
(
token
):
'''
'''
...
@@ -40,30 +22,11 @@ def verify(token):
...
@@ -40,30 +22,11 @@ def verify(token):
'''
'''
try
:
try
:
payload
=
jwt
.
decode
(
token
,
SIGNING_KEY
,
algorithms
=
[
'HS256'
])
TokenService
.
verify
(
"Bearer "
+
token
)
except
:
return
Response
(
status
=
401
,
response
=
f
'Invalid JWT token'
)
# check if all needed fields are in the payload
if
not
"username"
in
payload
or
not
"created_at"
in
payload
or
not
"valid_until"
in
payload
:
return
Response
(
status
=
401
,
response
=
f
'Invalid JWT token'
)
try
:
UserService
.
get_by_username
(
payload
[
"username"
])
except
ValueError
as
e
:
# return 400 if the user does not exist
return
Response
(
status
=
400
,
response
=
str
(
e
))
# check if token has already expired
token_created_at
=
datetime
.
strptime
(
payload
[
"created_at"
],
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S.
%
f'
)
valid_until
=
datetime
.
strptime
(
payload
[
"valid_until"
],
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S.
%
f'
)
now
=
datetime
.
now
()
if
now
<=
token_created_at
or
now
>=
valid_until
:
return
Response
(
status
=
401
,
response
=
f
'Token expired'
)
# everthing is fine
return
Response
(
status
=
200
)
return
Response
(
status
=
200
)
except
ValueError
as
e
:
return
Response
(
status
=
401
,
response
=
str
(
e
))
def
authenticate
():
def
authenticate
():
'''
'''
...
@@ -75,7 +38,7 @@ def authenticate():
...
@@ -75,7 +38,7 @@ def authenticate():
try
:
try
:
user
=
UserService
.
get_by_credentials
(
username
,
data
[
"password"
])
user
=
UserService
.
get_by_credentials
(
username
,
data
[
"password"
])
return
{
"token"
:
generate_token
(
user
)}
return
{
"token"
:
TokenService
.
generate_token
(
user
)}
except
ValueError
as
e
:
except
ValueError
as
e
:
# return 400 if the user does not exist or the password is wrong
# return 400 if the user does not exist or the password is wrong
return
Response
(
status
=
400
,
response
=
str
(
e
))
return
Response
(
status
=
400
,
response
=
str
(
e
))
...
...
src/rest-gateway/app/services/login_wrapper.py
0 → 100644
View file @
9e4844c1
from
functools
import
wraps
from
flask
import
g
,
request
,
redirect
,
url_for
def
login_required
(
f
):
@
wraps
(
f
)
def
decorated_function
(
*
args
,
**
kwargs
):
auth
=
request
.
authorization
if
auth
==
None
:
return
redirect
(
url_for
(
'/api.rest_user_forbidden'
,
next
=
request
.
url
))
return
f
(
*
args
,
**
kwargs
)
return
decorated_function
src/rest-gateway/app/services/token_service.py
0 → 100644
View file @
9e4844c1
# global imports (dont't worry, red is normal)
from
db.entities.user
import
User
from
services.user_service
import
UserService
import
jwt
from
datetime
import
datetime
,
timedelta
from
typing
import
Dict
SIGNING_KEY
=
"yteNrMy6142WKwp8fKfrHkS5nlFpxtHgOXJh1ZPsOrV_gTcsO9eMY7aB7HUzRbTRO9dmZhCl3FdPtuvMe3K8aBA_wc2MmHRo8IkUIGmvUJGsAxKFClN_6oNW5fEvoeVKiL1krA-qjWbR_em-WksePgPoTsySW7QbKdi4f7cwuyK2_JZ2fQj9hDKlfJ2GzMXkKiWcfyCTr30yC6BviAFeRDD_Bpvg6znsrXr53Tq66hnwDwQ6QU7aHVu-bERblKZTYuvkSxsov6yRMEVWQoiuBITsQtIOcgSWK4Dy3BjSbqoIcKw3WG-s3wx1lTen19QbEu8vJC64e0iGeGDWT6vbtg"
TOKEN_VALIDITY_IN_DAYS
=
1
# needed by connexion, do not remove!
def
verifyToken
(
token
,
**
kwargs
)
->
Dict
:
try
:
user
=
TokenService
.
verify
(
token
)
except
ValueError
as
e
:
print
(
f
'ERROR DURING TOKEN VALIDATION: {str(e)}'
)
return
None
return
{
"sub"
:
user
.
username
}
class
TokenService
:
@
staticmethod
def
generate_token
(
user
:
User
)
->
str
:
'''
creates a JWT token for a user which has the following fields:
- username
- created_at
- valid_until
'''
created_at
=
datetime
.
now
()
valid_until
=
created_at
+
timedelta
(
days
=
1
)
return
jwt
.
encode
(
{
'username'
:
user
.
username
,
'created_at'
:
str
(
created_at
),
'valid_until'
:
str
(
valid_until
),
},
SIGNING_KEY
,
algorithm
=
'HS256'
)
.
decode
(
"utf-8"
)
@
staticmethod
def
verify
(
token
:
str
,
**
kwargs
)
->
User
:
'''
verifies the validity of a JWT token. Raises a ValueError if one of the tests failes
performs the following tests (int this order):
- is the JWT token parsable? (it has not been damaged + the signature is valid)
- does the payload contain all necessary fields?
- does the user specified by the payload exist?
- is the expiration/creation date sound?
@params:
token - Required : JWT token from authorization header, must start with "Bearer "
'''
if
not
token
.
startswith
(
"Bearer "
):
raise
ValueError
(
'Invalid JWT token (must be a Bearer string)'
)
token
=
token
[
7
:]
try
:
payload
=
jwt
.
decode
(
token
,
SIGNING_KEY
,
algorithms
=
[
'HS256'
])
except
:
raise
ValueError
(
'Invalid JWT token (decoding failed)'
)
# check if all needed fields are in the payload
if
not
"username"
in
payload
or
not
"created_at"
in
payload
or
not
"valid_until"
in
payload
:
return
'Invalid JWT token (missing fields)'
user
=
UserService
.
get_by_username
(
payload
[
"username"
])
# check if token has already expired
token_created_at
=
datetime
.
strptime
(
payload
[
"created_at"
],
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S.
%
f'
)
valid_until
=
datetime
.
strptime
(
payload
[
"valid_until"
],
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S.
%
f'
)
now
=
datetime
.
now
()
if
now
<=
token_created_at
or
now
>=
valid_until
:
raise
ValueError
(
'Invalid JWT token (token expired)'
)
return
user
\ No newline at end of file
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