Kasutaja tuvastamine veebis

Allikas: eid.eesti.ee
Redaktsioon seisuga 3. märts 2014, kell 01:01 kasutajalt Taneltammet (arutelu | kaastöö)
Jump to navigation Jump to search

Mis puhul kasutaja tuvastamiseks eID-d kasutada

Enamus veebilehti kas ei vaja üldse kasutaja tuvastamist või siis jätab kasutaja meelde cookie abil, tuvastamata seejuures tema nime või emaili. Kui kasutajat on vaja reaalselt tuvastada, siis kasutatakse Eestis eeskätt järgmisi meetodeid:

  • Kasutajanime ja parooli küsimine.
  • Facebooki või Google või mõne analoogilise sotsiaalvõrgustiku teenuste tarvitamine kasutaja tuvastamiseks.
  • eID tarvitamine kasutaja tuvastamiseks.

eID eeliseks muude viiside ees on eeskätt oluliselt suurem turvalisus ja kasutaja reaalse nime ning isikukoodi teadasaamine ilma administraatoripoolse vajaduseta aktiivselt kasutajate andmebaasi hallata.

Pane tähele, et veebis kasutaja tuvastamine ID-kaardiga töötab väga erinevalt kasutaja tuvastamisest mobiil-ID-ga. Vaatame neid eraldi, alustades ID-kaardist.

Veebirakenduse kasutaja tuvastamine ID-kaardiga

Selleks, et ehitada veebirakendusele külge kasutaja tuvastamine ID-kaardi abil, on vaja teha kolme asja:

  • Panna kokku vajalikud sertifikaadifailid: mh on selleks vaja tellida Sertifitseerimiskeskuselt kinnitus oma serdifikaadifailile. Esialgseks testimiseks seda kinnitust vaja ei ole.
  • Seadistada veebiserver kasutama turvalist https sidet koos eelnevalt kokkupandud sertifikaadifailidega: otsest programeerimist siin vaja ei ole, veebiserveri (Apache, IIS, Nginx) standarfunktsionaalsuse seas on oskus ise ID-kaardiga üle võrgu suhelda.
  • Lisada oma veebirakendusele kasutaja ID-kaardilt loetud info küsimine nn keskkonnamuutujast (sinna paneb selle info veebiserver) ja selle info lahtiharutamine vajalikeks tükkideks: tüüpiliselt kasutaja nimi ja isikukood. Siin on vaja kas ise veidi programmeerida või kasutada alltoodud näiteprogrammide juppe.

Serfikaadifailide kokkupanek

Sertifikaadifailide ise kokkupanekuks kasuta openssl rakendust Linuxis pluss standardseid Linuxi abi-utiliite nagu wget, cat jne. Tööprotsessid toodud failide konkreetsed nimed võid soovi korral ära muuta, kuid lihtsam on täita neid käske muutma kujul:

Loo fail server.key

 openssl genrsa -out server.key 1024 (
 

Loo fail server.csr, vastates mitmetele küsimustele:

 req -new -key server.key -out server.csr

Loo fail server.crt

 openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Hangi AS Sertifitseerimiskeskusest kesksed sertifikaadid, vt ka https://sk.ee/repositoorium/sk-sertifikaadid/

 wget http://sk.ee/upload/files/JUUR-SK.PEM.cer
 wget http://sk.ee/upload/files/EECCRCA.pem.cer
 wget http://sk.ee/upload/files/ESTEID-SK%202007.PEM.cer
 wget http://sk.ee/upload/files/ESTEID-SK%202011.pem.cer

Liida mitu sertifikaati üheks failiks:

 cat JUUR-SK.PEM.cer EECCRCA.pem.cer 'ESTEID-SK 2007.PEM.cer' 'ESTEID-SK 2011.pem.cer' > id.crt

Hangi AS Sertifitseerimiskeskusest tühistusnimekirjad. NB! Neid ei lähe tingimata tarvis, täpsem seletus järgnevas. Vt ka http://sk.ee/repositoorium/CRL/

 wget http://www.sk.ee/crls/esteid/esteid2007.crl
 wget http://www.sk.ee/crls/juur/crl.crl
 wget http://www.sk.ee/crls/eeccrca/eeccrca.crl
 wget http://www.sk.ee/repository/crls/esteid2011.crl

Konverteeri tühistusnimekirjad PEM formaati

 openssl crl -in esteid2007.crl -out esteid2007.crl -inform DER
 openssl crl -in crl.crl -out crl.crl -inform DER
 openssl crl -in eeccrca.crl -out eeccrca.crl -inform DER
 openssl crl -in esteid2011.crl -out esteid2011.crl -inform DER  

Loo symlingid, mille failinimi baseerub CRL faili hashil:

 ln -s crl.crl `openssl crl -hash -noout -in crl.crl`.r0
 ln -s esteid2007.crl `openssl crl -hash -noout -in esteid2007.crl`.r0
 ln -s eeccrca.crl `openssl crl -hash -noout -in eeccrca.crl`.r0
 ln -s esteid2011.crl `openssl crl -hash -noout -in esteid2011.crl`.r0  

Edaspidiseks uuendamiseks vaata:

 http://id.ee/public/renew.sh

Alternatiivina siintoodule võid vaadata ka lühemat juhendit või pikemat analoogilist juhendit AS Sertifitseerimiskeskuselt.

Veebiserveri konfigureerimine

Vaatame siinkohas põhjalikumalt Apache veebiserveri konfigureerimist.

Apache konfigureerimine

Alternatiivina siintoodule võid vaadata ka lühemat juhendit või pikemat analoogilist juhendit AS Sertifitseerimiskeskuselt.

IIS konfigureerimine

IIS konfigureerimise juhend AS Sertifitseerimiskeskuselt

Oma rakendusele kasutajainfo küsimise lisamine

Veebiserver paigutab ID-kaardilt loetud info standardsel moel süsteemi nn keskkonnamuutujatesse. Olulised muutujad on seejuures

  • SSL_CLIENT_S_DN mille oodatav väärtus on taoline:
  /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/SN=SMITH/GN=JOHN/serialNumber=37504170511
  • SSL_CLIENT_VERIFY mille väärtus peab olema SUCCESS

Seejuures on täpitähtede kodeerimise viis SSL_CLIENT_S_DN tekstis erinev vanematel ja uuematel ID-kaartidel. Vanematel kaartidel on täpitähtede asemel kodeeritud sümbolid: \\x01`\\x00 jne mis esitavad kahebaidiseid UCS-2/UTF-16 kujul tähti: kõik erimärgid on asendatud kahe kaldkriipsu ja märgi koodiga HEX süsteemis. Uuemad kaardid kasutavad täpitähtede jaoks UTF-8 kodeeringut.

Järgnevad kolm näite-veebirakendust PHP-s, Pythonis ja Rubys loevad keskkonnamuutujast vajalikud väärtused, teisendavad tähestikud ja harutavad välja isiku eesnime, perenime ja isikukoodi, mis seejärel veebilehel kuvatakse. Kui isikutuvastus või konvertimine ebaõnnestuvad, antakse vastav teade. Mitte mingit täiendavat tarkvara peale siintoodud lähtekoodide näidetes vaja ei lähe.

PHP näiterakendus

<?php 
header ("Content-Type: text/html; charset=utf-8");
  
// Get user information obtained by Apache from the Estonian ID card.
// Return list [last_name,first_name,person_code] or None if fails. 

function get_user () {
  // get relevant environment vars set by Apache
  // SSL_CLIENT_S_DN example:
  //  /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  //  SN=SMITH/GN=JOHN/serialNumber=37504170511
  $ident=getenv("SSL_CLIENT_S_DN");  
  $verify=getenv("SSL_CLIENT_VERIFY");
  // check and parse the values
  if (!$ident || $verify!="SUCCESS") return False;
  $ident=certstr2utf8($ident); // old cards use UCS-2, new cards use UTF-8
  if (strpos($ident,"/C=EE/O=ESTEID/OU=authentication")!=0) return False;
  $ps=strpos($ident,"/SN=");
  $pg=strpos($ident,"/GN=");
  $pc=strpos($ident,"/serialNumber=");
  if (!$ps || !$pg || !$pc) return False;
  $res=array(substr($ident,$ps+4,$pg-($ps+4)), 
             substr($ident,$pg+4,$pc-($pg+4)), 
             substr($ident,$pc+14,strlen($ident)-$pc+14));
  return $res;
}  

// Convert names from UCS-2/UTF-16 to UTF-8.
// Function taken from help.zone.eu.

function certstr2utf8 ($str) {
  $str = preg_replace ("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))", $str);       
  $result="";
  $encoding=mb_detect_encoding($str,"ASCII, UCS2, UTF8");
  if ($encoding=="ASCII") {
    $result=mb_convert_encoding($str, "UTF-8", "ASCII");
  } else {
    if (substr_count($str,chr(0))>0) {
      $result=mb_convert_encoding($str, "UTF-8", "UCS2");
    } else {
      $result=$str;
    }
  }
  return $result;
}

//  Actual script to run

$user=get_user();
if (!$user) echo ("Authentication failed.");
else {
  echo "Last name: " . $user[0] . "<br>";
  echo "First name: " . $user[1] . "<br>";
  echo "Person code: " . $user[2] . "<br>";
}

?>

Pythoni näiterakendus: pane see katseks serveri cgi-bin kataloogi

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, re

def get_user():
  """Get user information obtained by Apache from the Estonian ID card.
     Returns list [last_name,first_name,person_code] or None if fails. 
  """
  # get relevant environment vars set by Apache
  # SSL_CLIENT_S_DN example:
  # /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  # SN=SMITH/GN=JOHN/serialNumber=37504170511
  ident=os.getenv('SSL_CLIENT_S_DN')
  verify=os.getenv('SSL_CLIENT_VERIFY')
  # check and parse the values
  if not ident or verify!="SUCCESS": return None
  ident=str2utf8(ident) # old cards use UCS-2, new cards use UTF-8
  if not ident.startswith("/C=EE/O=ESTEID/OU=authentication"): return None
  ps=ident.find("/SN=")
  pg=ident.find("/GN=")
  pc=ident.find("/serialNumber=")
  if ps<=0 or ps<=0 or pc<=0: return None
  res=[ident[ps+4:pg], ident[pg+4:pc], ident[pc+14:]]
  return res

def str2utf8(s):
  """Convert names from UCS-2/UTF-16 to UTF-8.""" 
  try:
    s=re.sub("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))", s);
    if s.find("\x00")>0: 
      x=s.decode(encoding="utf-16") 
      s=x.encode(encoding="utf-8")    
      return s
    return s
  except:
    return "" # conversion failed    

# Actual script to run  

print("Content-type: text/html; charset=utf-8\n\n")
user=get_user()
if not user: 
  print("Authentication failed.")
else:
  print("Last name: "+user[0]+"<br>")
  print("First name: "+user[1]+"<br>")
  print("Person code: "+user[2]+"<br>")

Ruby näiterakendus: pane see katseks serveri cgi-bin kataloogi

#!/usr/bin/ruby

require 'iconv'

# Get user information obtained by Apache from the Estonian ID card.
# Return list [last_name,first_name,person_code] or nil if fails. 

def get_user
  # Get user information obtained by Apache from the Estonian ID card.
  #  Returns list [last_name,first_name,person_code] or nil if fails. 
  # get relevant environment vars set by Apache
  # SSL_CLIENT_S_DN example:
  # /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  # SN=SMITH/GN=JOHN/serialNumber=37504170511
  ident=ENV["SSL_CLIENT_S_DN"]
  verify=ENV["SSL_CLIENT_VERIFY"];
  # check and parse the values
  if !ident or verify!="SUCCESS"
    return nil
  end    
  ident=str2utf8(ident) # old cards use UCS-2, new cards use UTF-8
  if ident.index("/C=EE/O=ESTEID/OU=authentication")!=0
    return nil
  end  
  ps=ident.index("/SN=")
  pg=ident.index("/GN=")
  pc=ident.index("/serialNumber=")
  if !ps or !pg or !pc
    return nil
  end  
  res=[ident[ps+4..pg-1], ident[pg+4..pc-1], ident[pc+14..-1]]
  return res
end  

# Convert names from UCS-2/UTF-16 to UTF-8.

def str2utf8(s)
  begin
    s=s.gsub("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))")
    if s.index("\x00")
      conv=Iconv.new("UTF-8//IGNORE","UTF-16")
      s=conv.iconv(s) 
      return s
    end  
    return s
  rescue
    return "" # conversion failed 
  end  
end    

# Actual script to run

puts "Content-type: text/html; charset=utf-8\n\n"
user=get_user()
if !user 
  puts "Authentication failed."
else
  puts "Last name: "+user[0]+"<br>"
  puts "First name: "+user[1]+"<br>"
  puts "Person code: "+user[2]+"<br>"
end  

Veebirakenduse kasutaja tuvastamine mobiil-ID-ga

Rakenduse näide ja lähtekood AS Sertifitseerimiskeskuselt