# Authentification

## Introduction

Le but du module d'authentification est de pouvoir facilement faire des blocks de code permettant une authentification personalisée. Il est possible de le faire grâce a cette architecture. Pour la première version de cette fonctionalitée, l'introduction de OICD et de OAuth sont priorisé ainsi que la migration du module d'authentification simple.


## Déconstruction simple de la structure
La structure est la suivante : 

Le AuthManager s'occupe de centraliser les requetes d'authentifications. Ce qui veux dire d'initialiser les autres modules et d'être la source de véritée dans au sujet de l'authentification. Les modules sont automatiquement chargé par l'utilisation de variables d'environment.

Le module s'occupe de creer les routes nécéssaires pour son fonctionnement et de créer les utilisateurs. Ces modules vont appeller le AuthManager afin de confirmer leurs actions avec le login/register de celui-ci

Dans le cas de modules plus complexe, tels que le module Passport, la chaine peut être prolongée afin de maintenir centralisée les actions. Chaque connecteur de PassportJs est initialisé par le module de PassportJs.


## Besoins exprimés


Modularité et généricité : 

- Le système d'authentification doit être adaptable à diverses configurations, notamment pour répondre aux exigences spécifiques des différentes universités ou institutions. 

Utilisation de différentes méthodes d'authentification : 

- L'application doit permettre de gérer plusieurs fournisseurs d'authentification (SSO, LDAP, OAuth, etc.) de manière centralisée et flexible. 

Facilité de configuration : 

- Le système doit permettre une configuration simple et flexible, adaptée à différents environnements (développement, production, etc.). 

Gestion des permissions : 

- Il doit être possible de définir et de mapper facilement les permissions et les rôles des utilisateurs pour sécuriser l’accès aux différentes fonctionnalités de l’application. 

Maintien de la connexion : 

- Le système doit garantir la persistance de la connexion pendant toute la durée de l'utilisation de l'application (exemple : quiz), avec la possibilité de se reconnecter sans perte de données en cas de déconnexion temporaire. 

## Recis utilisateurs pris en comptes

- En tant qu'utilisateur de projet FOSS, je veux que le module d'authentifcation soit modulaire et générique afin de l'adapter a mes besoins. 
- En tant qu'administrateur, je veux que les droits des utilisateurs soient inférés par l'authentificateur de l'établissement.
- En tant qu'administrateur, je veux que la configuration des authentificateur soit simple
- En tant qu'administrateur, je veux configurer les connections a partir de variables d'env ou fichier de config.
- En tant qu'utilisateur, je veux que ma connexion soit stable.
- En tant qu'utilisateur, je veux pouvoir me reconnecter a une salle s'il y arrive un problème de connexion.

## Diagrammes

### Structure
```plantuml
@startuml

package Backend {
class AuthManager{
    +IAuthModule[] auths
    #userInfos
    
    -load()
    -registerAuths()
    +showAuths()

    +authStatus()
    +logIn(UserInfos)
    +register(UserInfos)
    +logOut()
}

interface IAuthModule{
    +registerAuth()
    +authenticate()
    +register()
    +showAuth()
}

class SimpleFormAuthModule{

}

class PassportAuthModule{
    IPassportProviderDefinition[] providers
}

Interface IPassportProviderDefinition{
    +name
    +type
}

class OAuthPassportProvider{
    +clientId
    +clientSecret
    +configUrl
    +authorizeUrl
    +tokenUrl
    +userinfoUrl
    +logoutUrl
    +JWKSUrl
}

IAuthModule <|-- SimpleFormAuthModule
IAuthModule <|-- PassportAuthModule
IPassportProviderDefinition <|-- OAuthPassportProvider

AuthManager -> IAuthModule
PassportAuthModule -> IPassportProviderDefinition
}

package Frontend{ 
    class AuthDrawer{
        +IAuthVisual[] getAuthsVisual()
        +drawAuths()
    }

    Interface IAuthVisual{
        +draw()
    }

    class FormVisual{
        +FormInput[] formInputs
    }

    interface FormInput{
        +name
        +label
        +type
        +value
    }

    AuthDrawer -> IAuthVisual
    IAuthVisual <|-- FormVisual
    FormVisual -> FormInput
}

@enduml
```


### Explication des communications :  Passport Js
```plantuml
@startuml

box "Frontend"
participant User
Participant App
end box

box "Backend"
participant PassportAuthModule
participant Db
participant AuthManager
end box

box "Auth Server"
participant AuthServer
end box

User -> App : Get auth page
App -> User : auth page

User -> App : click OAuth button
App -> User : redirect to OAuth

User -> AuthServer: Login
AuthServer -> User: Redirect to Auth endpoint with token

User -> PassportAuthModule: Authenticate with token

PassportAuthModule -> AuthServer: get user info
AuthServer -> PassportAuthModule: userInfo

alt login
    PassportAuthModule -> Db : fetch local userInfo
    Db->PassportAuthModule: userInfo
    PassportAuthModule -> PassportAuthModule: Merge userInfo definition
    PassportAuthModule -> Db : update user profile
    Db->PassportAuthModule: userInfo
end 

alt register
    PassportAuthModule -> Db : fetch local userInfo
    Db->PassportAuthModule: null
    PassportAuthModule -> Db : create user profile
    Db->PassportAuthModule: userInfo
end 

PassportAuthModule -> AuthManager : login(userInfos)

AuthManager -> User: Give refresh token + Redirect to page
User -> App: get /
App -> User: Show Authenticated /
@enduml
```

### Explication des communications : SimpleAuth
```plantuml
@startuml

box "Frontend"
participant User
Participant App
end box

box "Backend"
participant SimpleAuthModule
participant Db
participant AuthManager
end box

User -> App : Get auth page
App -> User : auth page


alt Login
    User -> App : Send Login/Pass

    App -> SimpleAuthModule: Send login/pass

    SimpleAuthModule -> Db: get user info
    Db->SimpleAuthModule: user info
    SimpleAuthModule -> SimpleAuthModule: Validate Hash
end

alt register
    User -> App : Send Username + Password + Email

    App -> SimpleAuthModule: Send Username + Password + Email

    SimpleAuthModule -> Db: get user info
    Db -> SimpleAuthModule : null

    SimpleAuthModule -> Db: put user info
end 

SimpleAuthModule -> AuthManager: userInfo
AuthManager -> User: Give refresh token + Redirect to page
User -> App: get /
App -> User: Show Authenticated /
@enduml
```

### Comment les boutons sont affichés
```plantuml
@startuml

box "FrontEnd"
participant User
Participant FrontEnd
Participant AuthDrawer
end box

box "BackEnd"
participant API
participant AuthManager
participant Db
participant IAuthModule
end box

API -> API : load global configurations

create AuthManager
API -> AuthManager : instanciate with auth configurations


create IAuthModule
AuthManager -> IAuthModule : instanciate array

loop For each auth in auths
    AuthManager -> IAuthModule : register
    IAuthModule -> API : register routes
    API -> IAuthModule : route registration confirmation
    IAuthModule -> AuthManager : module registration confirmation
end

User -> FrontEnd : get login page

alt already logged in
    FrontEnd -> User: redirected to authenticated page
end

FrontEnd -> AuthDrawer : get auth visual
AuthDrawer -> API : get auth form data

API -> AuthManager : get auth form data


loop For each auth in auths
    AuthManager -> IAuthModule : get form data
    IAuthModule -> AuthManager : form data
end

AuthManager -> API : auth fom data
API -> AuthDrawer : auth form data

AuthDrawer -> AuthDrawer : make auth html
AuthDrawer -> FrontEnd : auth HTML
FrontEnd -> User : show auth page


@enduml
```

### Comment les sessions sont conservées
```plantuml
@startuml
    box "Frontend"
    participant User
    Participant App
    end box

    box "Backend"
    participant AuthManager
    participant IAuthModules
    end box

    App -> AuthManager : send refresh token

    AuthManager -> IAuthModules: ForEach check if logged
    IAuthModules -> AuthManager: is authenticated ?
    
    alt one logged in
        AuthManager -> App : send new token
    end

    alt all logged out
        AuthManager -> App : send error
        App -> App : destroy token
        App -> User : redirect to login page
    end

@enduml
```

## Configuration des variables d'environnement 

Example de configuration du fichier : `server/auth_config.json` :

```json
{
    "auth": {
        "passportjs": // Module
        [
            {
                "gmatte": { // Nom du sous-module Passport
                    "type": "oauth", // type
                    "OAUTH_AUTHORIZATION_URL": "https://auth.gmatte.xyz/application/o/authorize/",
                    "OAUTH_TOKEN_URL": "https://auth.gmatte.xyz/application/o/token/",
                    "OAUTH_USERINFO_URL": "https://auth.gmatte.xyz/application/o/userinfo/",
                    "OAUTH_CLIENT_ID": "--redacted--",
                    "OAUTH_CLIENT_SECRET": "--Redacted--",
                    "OAUTH_ADD_SCOPE": "groups", // scopes supplémentaire nécéssaire pour le pivot
                    "OAUTH_ROLE_TEACHER_VALUE": "groups_evaluetonsavoir-prof", // valeur de pivot afin de définir un enseignant
                    "OAUTH_ROLE_STUDENT_VALUE": "groups_evaluetonsavoir" // valeur de pivot afin de définir un étudiant
                }
            },
            {
                "etsmtl":{
                    "type":"oidc",
                    "OIDC_CONFIG_URL":"https://login.microsoftonline.com/70aae3b7-9f3b-484d-8f95-49e8fbb783c0/v2.0/.well-known/openid-configuration",
                    "OIDC_CLIENT_ID": "--redacted--",
                    "OIDC_CLIENT_SECRET": "--redacted--",
                    "OIDC_ADD_SCOPE": "",
                    "OIDC_ROLE_TEACHER_VALUE": "groups_evaluetonsavoir-prof",
                    "OIDC_ROLE_STUDENT_VALUE": "groups_evaluetonsavoir"
                }
            }
        ],
        "simpleauth":{}
    }
}
```