mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-11-10 08:57:25 +01:00
commit
987f77170f
@ -16,6 +16,9 @@ The most important routines in auth are:
|
|||||||
The http router calls auth in the following cases:
|
The http router calls auth in the following cases:
|
||||||
* `r.Handle("/login", authentication.Login( ... )).Methods(http.MethodPost)`:
|
* `r.Handle("/login", authentication.Login( ... )).Methods(http.MethodPost)`:
|
||||||
The POST request on the `/login` route will call the Login callback.
|
The POST request on the `/login` route will call the Login callback.
|
||||||
|
* `r.Handle("/jwt-login", authentication.Login( ... ))`:
|
||||||
|
Any request on the `/jwt-login` route will call the Login callback. Intended
|
||||||
|
for use for the JWT token based authenticators.
|
||||||
* Any route in the secured subrouter will always call Auth(), on success it will
|
* Any route in the secured subrouter will always call Auth(), on success it will
|
||||||
call the next handler in the chain, on failure it will render the login
|
call the next handler in the chain, on failure it will render the login
|
||||||
template.
|
template.
|
||||||
@ -50,7 +53,6 @@ The Login function (located in `auth.go`):
|
|||||||
object is returned.
|
object is returned.
|
||||||
- Creates a new session object, stores the user attributes in the session and
|
- Creates a new session object, stores the user attributes in the session and
|
||||||
saves the session.
|
saves the session.
|
||||||
- If the user does not yet exist in the database try to add the user
|
|
||||||
- Starts the `onSuccess` http handler
|
- Starts the `onSuccess` http handler
|
||||||
|
|
||||||
## Local authenticator
|
## Local authenticator
|
||||||
@ -71,11 +73,20 @@ if e := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(r.FormValue(
|
|||||||
|
|
||||||
## LDAP authenticator
|
## LDAP authenticator
|
||||||
|
|
||||||
This authenticator is applied if
|
This authenticator is applied if the user was found in the database and its
|
||||||
|
AuthSource is LDAP:
|
||||||
```
|
```
|
||||||
return user != nil && user.AuthSource == AuthViaLDAP
|
if user != nil {
|
||||||
|
if user.AuthSource == schema.AuthViaLDAP {
|
||||||
|
return user, true
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the option `SyncUserOnLogin` is set it tried to sync the user from the LDAP
|
||||||
|
directory. In case this succeeds the user is persisted to the database and can
|
||||||
|
login.
|
||||||
|
|
||||||
Gets the LDAP connection and tries a bind with the provided credentials:
|
Gets the LDAP connection and tries a bind with the provided credentials:
|
||||||
```
|
```
|
||||||
if err := l.Bind(userDn, r.FormValue("password")); err != nil {
|
if err := l.Bind(userDn, r.FormValue("password")); err != nil {
|
||||||
@ -88,33 +99,34 @@ if err := l.Bind(userDn, r.FormValue("password")); err != nil {
|
|||||||
|
|
||||||
Login via JWT token will create a session without password.
|
Login via JWT token will create a session without password.
|
||||||
For login the `X-Auth-Token` header is not supported. This authenticator is
|
For login the `X-Auth-Token` header is not supported. This authenticator is
|
||||||
applied if the Authorization header is present:
|
applied if the Authorization header or query parameter login-token is present:
|
||||||
```
|
```
|
||||||
return r.Header.Get("Authorization") != ""
|
return user, r.Header.Get("Authorization") != "" ||
|
||||||
|
r.URL.Query().Get("login-token") != ""
|
||||||
```
|
```
|
||||||
|
|
||||||
The Login function:
|
The Login function:
|
||||||
* Parses the token
|
* Parses the token and checks if it is expired
|
||||||
* Check if the signing method is EdDSA or HS256 or HS512
|
* Check if the signing method is EdDSA or HS256 or HS512
|
||||||
* Check if claims are valid and extracts the claims
|
* Check if claims are valid and extracts the claims
|
||||||
* The following claims have to be present:
|
* The following claims have to be present:
|
||||||
- `sub`: The subject, in this case this is the username
|
- `sub`: The subject, in this case this is the username
|
||||||
- `exp`: Expiration in Unix epoch time
|
- `exp`: Expiration in Unix epoch time
|
||||||
- `roles`: String array with roles of user
|
- `roles`: String array with roles of user
|
||||||
* In case user is not yet set, which is usually the case:
|
* In case user does not exist in the database and the option `SyncUserOnLogin`
|
||||||
- Try to fetch user from database
|
is set add user to user database table with `AuthViaToken` AuthSource.
|
||||||
- In case user is not yet present add user to user database table with `AuthViaToken` AuthSource.
|
|
||||||
* Return valid user object
|
* Return valid user object
|
||||||
|
|
||||||
## JWT Cookie Session authenticator
|
## JWT Cookie Session authenticator
|
||||||
|
|
||||||
Login via JWT cookie token will create a session without password.
|
Login via JWT cookie token will create a session without password.
|
||||||
It is first checked if the required configuration keys are set:
|
It is first checked if the required configuration options are set:
|
||||||
* `publicKeyCrossLogin`
|
* `trustedIssuer`
|
||||||
* `TrustedExternalIssuer`
|
|
||||||
* `CookieName`
|
* `CookieName`
|
||||||
|
|
||||||
This authenticator is applied if the configured cookie is present:
|
and optionally the environment variable `CROSS_LOGIN_JWT_PUBLIC_KEY` is set.
|
||||||
|
|
||||||
|
This authenticator is applied if the configured cookie is present:
|
||||||
```
|
```
|
||||||
jwtCookie, err := r.Cookie(cookieName)
|
jwtCookie, err := r.Cookie(cookieName)
|
||||||
|
|
||||||
@ -131,9 +143,11 @@ The Login function:
|
|||||||
- Return public cross login key
|
- Return public cross login key
|
||||||
- Otherwise return standard public key
|
- Otherwise return standard public key
|
||||||
* Check if claims are valid
|
* Check if claims are valid
|
||||||
* Depending on the option `ForceJWTValidationViaDatabase ` the roles are
|
* Depending on the option `validateUser` the roles are
|
||||||
extracted from JWT token or taken from user object fetched from database
|
extracted from JWT token or taken from user object fetched from database
|
||||||
* Ask browser to delete the JWT cookie
|
* Ask browser to delete the JWT cookie
|
||||||
|
* In case user does not exist in the database and the option `SyncUserOnLogin`
|
||||||
|
is set add user to user database table with `AuthViaToken` AuthSource.
|
||||||
* Return valid user object
|
* Return valid user object
|
||||||
|
|
||||||
# Auth
|
# Auth
|
||||||
@ -154,7 +168,7 @@ Implemented in JWTAuthenticator:
|
|||||||
prefix
|
prefix
|
||||||
* Parse token and check if it is valid. The Parse routine will also check if the
|
* Parse token and check if it is valid. The Parse routine will also check if the
|
||||||
token is expired.
|
token is expired.
|
||||||
* If the option `ForceJWTValidationViaDatabase` is set it will ensure the
|
* If the option `validateUser` is set it will ensure the
|
||||||
user object exists in the database and takes the roles from the database user
|
user object exists in the database and takes the roles from the database user
|
||||||
* Otherwise the roles are extracted from the roles claim
|
* Otherwise the roles are extracted from the roles claim
|
||||||
* Returns a valid user object with AuthType set to AuthToken
|
* Returns a valid user object with AuthType set to AuthToken
|
||||||
|
@ -48,26 +48,8 @@ func (auth *Authentication) AuthViaSession(
|
|||||||
if session.IsNew {
|
if session.IsNew {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// var username string
|
// TODO: Check if session keys exist
|
||||||
// var projects, roles []string
|
|
||||||
//
|
|
||||||
// if val, ok := session.Values["username"]; ok {
|
|
||||||
// username, _ = val.(string)
|
|
||||||
// } else {
|
|
||||||
// return nil, errors.New("no key username in session")
|
|
||||||
// }
|
|
||||||
// if val, ok := session.Values["projects"]; ok {
|
|
||||||
// projects, _ = val.([]string)
|
|
||||||
// } else {
|
|
||||||
// return nil, errors.New("no key projects in session")
|
|
||||||
// }
|
|
||||||
// if val, ok := session.Values["projects"]; ok {
|
|
||||||
// roles, _ = val.([]string)
|
|
||||||
// } else {
|
|
||||||
// return nil, errors.New("no key roles in session")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
username, _ := session.Values["username"].(string)
|
username, _ := session.Values["username"].(string)
|
||||||
projects, _ := session.Values["projects"].([]string)
|
projects, _ := session.Values["projects"].([]string)
|
||||||
roles, _ := session.Values["roles"].([]string)
|
roles, _ := session.Values["roles"].([]string)
|
||||||
|
@ -228,8 +228,6 @@ func (la *LdapAuthenticator) Sync() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a connection pool or something like
|
|
||||||
// that so that connections can be reused/cached.
|
|
||||||
func (la *LdapAuthenticator) getLdapConnection(admin bool) (*ldap.Conn, error) {
|
func (la *LdapAuthenticator) getLdapConnection(admin bool) (*ldap.Conn, error) {
|
||||||
|
|
||||||
lc := config.Keys.LdapConfig
|
lc := config.Keys.LdapConfig
|
||||||
|
@ -154,11 +154,18 @@
|
|||||||
? statisticsSeries.mean.length
|
? statisticsSeries.mean.length
|
||||||
: series.reduce((n, series) => Math.max(n, series.data.length), 0)
|
: series.reduce((n, series) => Math.max(n, series.data.length), 0)
|
||||||
const maxX = longestSeries * timestep
|
const maxX = longestSeries * timestep
|
||||||
const maxY = thresholds != null
|
let maxY = null
|
||||||
? useStatsSeries
|
|
||||||
|
if (thresholds !== null) {
|
||||||
|
maxY = useStatsSeries
|
||||||
? (statisticsSeries.max.reduce((max, x) => Math.max(max, x), thresholds.normal) || thresholds.normal)
|
? (statisticsSeries.max.reduce((max, x) => Math.max(max, x), thresholds.normal) || thresholds.normal)
|
||||||
: (series.reduce((max, series) => Math.max(max, series.statistics?.max), thresholds.normal) || thresholds.normal)
|
: (series.reduce((max, series) => Math.max(max, series.statistics?.max), thresholds.normal) || thresholds.normal)
|
||||||
: null
|
|
||||||
|
if (maxY >= (10 * thresholds.normal)) { // Hard y-range render limit if outliers in series data
|
||||||
|
maxY = (10 * thresholds.normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const plotSeries = [{label: 'Runtime', value: (u, ts, sidx, didx) => didx == null ? null : formatTime(ts)}]
|
const plotSeries = [{label: 'Runtime', value: (u, ts, sidx, didx) => didx == null ? null : formatTime(ts)}]
|
||||||
const plotData = [new Array(longestSeries)]
|
const plotData = [new Array(longestSeries)]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user