Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
Example backend
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Thomas SAUVAGE
Example backend
Merge requests
!4
Trying to implement openid
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Trying to implement openid
trying-to-implement-openid
into
main
Overview
0
Commits
12
Pipelines
9
Changes
18
Merged
Thomas SAUVAGE
requested to merge
trying-to-implement-openid
into
main
1 year ago
Overview
0
Commits
12
Pipelines
9
Changes
2
Expand
0
0
Merge request reports
Compare
version 6
version 8
bb56ee87
1 year ago
version 7
46b8e605
1 year ago
version 6
bf3a901a
1 year ago
version 5
22f5d852
1 year ago
version 4
ff6ac180
1 year ago
version 3
c9d56632
1 year ago
version 2
f89e3662
1 year ago
version 1
84ba8be7
1 year ago
main (base)
and
latest version
latest version
058280df
12 commits,
1 year ago
version 8
bb56ee87
11 commits,
1 year ago
version 7
46b8e605
10 commits,
1 year ago
version 6
bf3a901a
8 commits,
1 year ago
version 5
22f5d852
6 commits,
1 year ago
version 4
ff6ac180
5 commits,
1 year ago
version 3
c9d56632
4 commits,
1 year ago
version 2
f89e3662
3 commits,
1 year ago
version 1
84ba8be7
2 commits,
1 year ago
Show latest version
2 files
+
17
−
4
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
2
Search (e.g. *.vue) (Ctrl+P)
app/Controllers/auth/authSigmaUser.ts
+
54
−
25
Options
import
Env
from
'
@ioc:Adonis/Core/Env
'
import
{
HttpContextContract
}
from
'
@ioc:Adonis/Core/HttpContext
'
import
{
SigmaUser
}
from
'
App/Utils/types
'
import
ElementNotFoundException
from
'
App/Exceptions/ElementNotFoundException
'
import
AuthCodeVerifier
from
'
App/Models/AuthCodeVerifier
'
import
User
from
'
App/Models/User
'
import
{
ClientMetadata
,
Issuer
,
generators
}
from
'
openid-client
'
const
AUTH_URL
=
'
https://auth.binets.fr
'
// ! Must be exactly the same as the one given to BR roots (with/without ending slash...)
const
CALLBACK_URL
=
'
http://localhost:3333/auth/sigmaUser/callback/
'
// Config for auth.binets.fr
const
AUTH_URL
=
'
https://auth.binets.fr
'
const
clientOptions
:
ClientMetadata
=
{
client_id
:
'
localhost
'
,
client_secret
:
Env
.
get
(
'
LOCALHOST_OPENID
_CLIENT_SECRET
'
),
client_id
:
Env
.
get
(
'
AUTH_CLIENT_ID
'
)
,
client_secret
:
Env
.
get
(
'
AUTH
_CLIENT_SECRET
'
),
redirect_uris
:
[
CALLBACK_URL
],
response_types
:
[
'
code
'
],
}
// ! Safe ? Works ? Risk of building up if people don't log in
let
verifiers
:
{
[
state
:
string
]:
string
}
=
{}
/** Login a user using `auth.binets.fr` which uses OpenId auth */
/** Login a user using `auth.binets.fr` which uses OpenId auth.
* The login is in 3 parts:
* - 1. Frontend asks for a url (call `loginSigmaUser`)
* - 2. User is redirected to this url, and he types his credentials
* - 3. `auth.binets.fr` sends a request to `callbackSigmaUser`
*/
export
const
loginSigmaUser
=
async
({
response
}:
HttpContextContract
)
=>
{
const
issuer
=
await
Issuer
.
discover
(
AUTH_URL
)
const
client
=
new
issuer
.
Client
(
clientOptions
)
const
codeVerifier
=
generators
.
codeVerifier
()
// Generate state and codeVerifier,
// used in the callback to verify the integrity of the request
const
state
=
generators
.
state
()
const
codeVerifier
=
generators
.
codeVerifier
()
verifiers
[
state
]
=
codeVerifier
// Store the codeVerifier in the DB
AuthCodeVerifier
.
create
({
state
,
codeVerifier
})
// Generate the url
const
codeChallenge
=
generators
.
codeChallenge
(
codeVerifier
)
const
url
=
client
.
authorizationUrl
({
scope
:
'
openid email profile groups
'
,
scope
:
'
openid email profile groups
'
,
// What info we want about the user
code_challenge
:
codeChallenge
,
code_challenge_method
:
'
S256
'
,
state
,
@@ -45,27 +55,46 @@ export const callbackSigmaUser = async ({ response, request, auth }: HttpContext
const
params
=
client
.
callbackParams
(
request
.
request
)
if
(
!
params
.
state
)
throw
new
Error
(
"
The response from the auth server doesn't have the state
"
)
const
codeVerifier
=
verifiers
[
params
.
state
]
if
(
!
params
.
state
)
throw
new
Error
(
"
The response from the auth server doesn't have a state
"
)
// Get the codeVerifier from the DB
const
{
codeVerifier
}
=
(
await
AuthCodeVerifier
.
find
(
params
.
state
))
??
{
codeVerifier
:
undefined
,
}
if
(
!
codeVerifier
)
throw
new
ElementNotFoundException
(
'
Code verifier not found in the database, maybe the user took too long to register
'
)
const
tokenSet
=
await
client
.
callback
(
CALLBACK_URL
,
params
,
{
code_verifier
:
codeVerifier
,
state
:
params
.
state
,
})
delete
verifiers
[
params
.
state
]
// Delete the codeVerifier
await
AuthCodeVerifier
.
query
().
delete
().
where
(
'
state
'
,
params
.
state
)
// Extract user infos from the response of `auth.binets.fr`
const
{
preferred_username
:
username
,
name
,
groups
}
=
tokenSet
.
claims
()
if
(
!
username
||
!
name
||
!
groups
)
throw
new
Error
(
'
The user given by the auth server is incomplete
'
)
const
receivedUser
=
{
username
,
name
,
groups
:
groups
as
string
[],
// ! UGLY
isSigmaUser
:
true
,
isAdmin
:
false
,
}
const
userExtended
=
tokenSet
.
claims
()
const
user
:
SigmaUser
=
{
username
:
userExtended
.
preferred_username
,
// Unique ?
name
:
userExtended
.
name
,
groups
:
userExtended
.
groups
,
}
as
SigmaUser
// Add user to User db
const
user
=
await
User
.
firstOrCreate
(
receivedUser
)
// console.log(tokenSet.claims())
// Generate token using Adonis JS default auth provider
const
token
=
await
auth
.
use
(
'
api
'
).
login
(
user
)
// const user = ...
// const token = await auth.use('api').login(user)
// return token
return
response
.
ok
(
tokenSet
.
claims
())
// TODO: Redirect to the frontend with the token ?
return
response
.
ok
({
token
,
user
})
}
Loading