-
Notifications
You must be signed in to change notification settings - Fork 15
Kevytkirjautuminen
eVakassa on tuki kuntalaisten kevytkirjautumiselle, joka tarkoittaa pelkällä käyttäjätunnuksella ja salasanalla kirjautumista vahvan tunnistautumisen sijaan. Tietoturvasyistä kevytkirjautunut kuntalainen pystyy käyttämään vain osaa järjestelmän toiminnoista, ja käyttöliittymässä lukkoikonin takana olevien toimintojen käyttö vaatii ensin vahvan tunnistautumisen. Kevytkirjautuneella käyttäjällä on apigw-sessioissa erillinen käyttäjätyyppi CITIZEN_WEAK, ja servicessä jokaisen kuntalaisen käyttöoikeustarkistuksen kohdalla määritetään sallitaanko operaatio kevytkirjautuneelle käyttäjälle vai ei.
Käyttäjätunnukset ja salasanat on tallennettu eVakan omaan tietokantaan citizen_user-tauluun, jossa salasanasta tallennetaan vain Argon2id-pohjainen hash ja hashaukseen käytetyt parametrit jotka on valittu OWASP-suosituksen mukaan. Kun käyttäjä yrittää kirjautua, kirjautumisen aikana syötetty salasana hashataan samoilla parametreilla, ja sen jälkeen tehdään hashien vakioaikainen vertailu josta päätellään oliko salasana oikein. Käyttäjän salasanaa ei siis tallenneta missään vaiheessa selkokielisenä, ja se on vain tilapäisesti muistissa tiettyjen kutsujen aikana missä se kulkee mukana parametrina.
Hashausparametrien tallennus tietokantaan salasanojen mukaan mahdollistaa hashausalgoritmien ja niiden parametrien vaihtamiseen tulevaisuudessa ilman että käyttäjien tarvitsee resetoida salasanoja. eVaka tukee Argon2id:n lisäksi vanhasta Keycloak-järjestelmästä migratoituja PBKDF2-pohjaisia salasanahasheja.
Esimerkki kantaan käyttäjäriville tallennetusta JSON-objektista, jossa on algoritmi, parametrit, ja jokaisen salasanavaihdon yhteydessä satunnaisesti generoitava salt:
{
"algorithm": {
"type": "Argon2id",
"hashLength": 32,
"version": "VERSION_13",
"memoryKbytes": 19456,
"iterations": 2,
"parallelism": 1
},
"salt": "G0yJIvnJLOrDczQ53Rt6bA==",
"hash": "96eQ779idMntywQEwNcVsn33Lfd4aJGRBeUHXNhKiwE="
}Jos onnistuneen kirjautumisen yhteydessä huomataan että kannassa oleva käyttäjän salasanan hash-algoritmi tai sen parametrit eivät vastaa tämänhetkistä järjestelmän oletusarvoa, tehdään automaattinen migraatio. Aktiivisten käyttäjien salasanat pysyvät siis automaattisesti järjestelmän suositusten mukaisina, jos Argon2id:stä halutaan vaihtaa toiseen algoritmiin tai oletusparametreja halutaan säätää tiukemmiksi. Muilta käyttäjiltä voidaan tarvittaessa poistaa käsin kannasta salasanat jos kirjautumisia ole tapahtunut jonkin siirtymäajan jälkeen, ja käyttäjät voivat palauttaa omat tunnukset normaalisti käyttöliittymän kautta.
eVakassa on yksinkertainen kuntakohtaisesti kustomoitava salasanojen validointimekanismi. Kuntakohtaisessa toteutuksessa täytyy toteuttaa PasswordSpecification-interface, joka kuvaa salasanan vaatimukset kahdessa osassa:
- Puhtaasti rakenteelliset vaatimukset kuvataan palauttamalla sopiva
PasswordConstraints-objekti, jolla voi rajata salasanan pituutta sekä pienten/isojen kirjaimien, numeroiden ja symbolien minimimääriä. Nämä vaatimukset validoidaan suoraan käyttöliittymässä, ja eVaka osaa näyttää sopivan validointivirheen välittömästi salasanaa syötettäessä. - Erillinen
isPasswordAcceptable-tarkistus voi käyttää mitä tahansa logiikkaa salasanan hyväksymiseen tai hylkäämiseen. Koska kyse on vapaamuotoisesta koodista joka ajetaan backendissä, tämä validointi ajetaan vasta kun käyttäjä painaa nappia vaihtaakseen salasanan. Tarkkoja validointivirheitä ei myöskään tueta, vaan käyttäjälle näytetään geneerinen virhe "salasana on liian helposti arvattava" josisPasswordAcceptablepalauttaa arvonfalse.
interface PasswordSpecification {
/** Returns the structural constraints for new passwords. */
fun constraints(): PasswordConstraints
/**
* Checks if an otherwise structurally valid password is acceptable.
*
* A password could be rejected for example if it's included in some list of too easily
* guessable passwords
*/
fun isPasswordAcceptable(dbc: Database.Connection, password: Sensitive<String>): Boolean
}Esimerkki:
class KuntaPasswordSpecification: PasswordSpecification {
fun constraints() = PasswordConstraints(
minLength = 8,
minUppers = 1,
minSymbols = 2
)
override fun isPasswordAcceptable(
dbc: Database.Connection,
password: Sensitive<String>,
): Boolean =
!password.contains("kunta", ignoreCase = true) && // kunnan nimeä ei saa olla sanasanassa
!dbc.read { it.isPasswordBlacklisted(password) } // tarkistetaan vielä erikseen kannassa oleva kieltolista
}eVaka tukee yksinkertaista salasanojen mustaa listaa, joka tallennetaan tietokantaan. Tätä voidaan käyttää edellisessä kappaleessa mainitussa isPasswordAcceptable-funktiossa jos halutaan vielä erikseen kieltää liian helppoja tai yleisesti käytettyjä salasanoja jotka menevät yksinkertaisesti rakenteellisesta validaatiosta (PasswordConstraints) läpi. Mustalle listalle voidaan lisätä salasanoja helposti kolmella eri tavalla:
- Käyttäjämällä automaattista yöllistä tiedostoista lataamismekanismia. Jos
evaka.password_blacklist_directorykonfiguraatioparametri on asetettu (env-muuttujaEVAKA_PASSWORD_BLACKLIST_DIRECTORY), eVaka käy läpi kyseisestä hakemistosta kaikki.txt-päätteiset tiedostot, ja lukee jokaiselta riviltä salasanan joka lisätään tietokannan mustalle listalle jos se menee rakenteellisista vaatimuksista läpi (PasswordConstraints). Tyhjät rivit skipataan, ja yöllinen ajo ei koskaan poista mustalta listalta mitään, vaikka.txt-tiedostot tai rakenteelliset vaatimukset muuttuisivat ajan myötä. Jos jotain salasanoja halutaan ehdottomasti poistaa mustalta listalta, ne pitää poistaa suoraan tietokantakyselyillä. - Kuntakohtaisessa toteutuksessa voi vapaasti kutsua
PasswordBlacklist.importPasswords-funktiota ja lisätä mustalle listalle mitä tahansa salasanoja - Mustaa listaa voi muokata suorilla tietokantakyselyillä
password_blacklist- japassword_blacklist_source-tauluihin
Huom, musta lista ei estä/poista takautuvasti jo käytössä olevia huonoja salasanoja.
Tietoturva on huomioitu kevytkirjautumisen toteutuksessa monella tavalla:
- Kaikki liikenne on HTTPS-salattuna
- eVakassa on yleinen IP-kohtainen rate limit joka kohdistuu kaikkiin API-kutsuihin
- eVakassa on yleinen header-pohjainen CSRF-tarkistus joka on käytössä myös kirjautumiskutsuissa
- Salasanat tallennetaan Argon2id-hasheina, jossa käytetään myös tallennuskertakohtaista salt-arvoa
- Sisäänkirjautumiskutsuissa on erillinen käyttäjäkohtainen rate limit
- Kirjautumiskutsussa hash-vertailu tehdään vakioaikaisesti (constant time), joten operaation kestosta ei voi päätellä kuinka monta merkkiä osui oikeaan
- Kevytkirjautumisen aktivointi vaatii vahvistetun sähköpostiosoitteen. Käyttäjä ei voi itse valita käyttäjätunnusta, vaan tunnus on aina vahvistettu sähköpostiosoite ja se ei voi olla kellään toisella käytössä
Copyright 2017-2025 City of Espoo
Sisältö on lisensoitu LGPL-2.1-or-later -lisenssillä
- eVaka
- Arkkitehtuuri
- Prosessikaaviot
- Henkilökunnan eVaka:
- Huoltajan evaka:
- Muita eVakan toiminnallisuuksia:
- Laskujen muodostus
- Perhesuhteet-(laskutus)
- Laitimmaislaskenta
- Asianhallintaprosessit ja metatiedot
- Päätökset
- Lomakepohjat ja lapsen asiakirjat
- Toimintojen avaukset
- Mobiililaitteiden liittäminen
- Viestintä
- Ehdottava esiopetusprosessi
- Yksikkö
- Integraatiot:
- Tarkempi tekninen dokumentaatio: