======= Service Provider: HowTo Shibboleth ======= \\ ====== Protocollo SAML2 ====== Le informazioni seguenti sono ad uso e consumo del referente tecnico che amministra il Service Provider Shibboleth ===== Informazioni ===== * EntityID dell’IdP: https://shibidp.unipr.it/idp/shibboleth * Metadata dell‘IdP: https://shibidp.unipr.it/idp/shibboleth * L’elenco degli attributi veicolati attraverso le asserzioni SAML sono * **Per tutti gli entityID** * attributeID="transientId" * attributeID="eduPersonTargetedID" * attributeID="eduPersonAffiliation" * attributeID="eduPersonScopedAffiliation"\\ * **Per gli entityID del tipo *.unipr.it** * attributeID="uniprID" * attributeID="uid" * attributeID="sn" * attributeID="givenName" * attributeID="mail" * attributeID="locality" * attributeID="server" * attributeID="principal" * attributeID="matricola" * attributeID="categoria" * attributeID="corsolaurea" * attributeID="uniprStudDip" * attributeID="codSISA" * attributeID="eduPersonPrimaryAffiliation" * attributeID="codicefiscale" * attributeID="uniprId" * attributeID="organizationalUnit" * samlSubjectID => urn:oasis:names:tc:SAML:attribute:subject-id * samlPairwiseID => urn:oasis:names:tc:SAML:attribute:pairwise-id Lato Service Provider configurare opportunamente l'attribute-map.xml per recepire gli attributi rilasciati:\\ * transientID viene codificato lato Idp nel seguente modo: nameFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" * eduPersonTargetedID -> * eduPersonAffiliation -> * eduPersonScopedAffiliation -> * uniprID -> * uid -> * sn -> * givenName -> * mail -> * locality -> * server -> * principal viene codificato nel seguente modo lato IdP: nameFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" * matricola -> * categoria -> * corsolaurea -> * uniprStudDip -> * codSISA -> * eduPersonPrimaryAffiliation -> * codicefiscale -> * uniprID -> * organizationalUnit -> * samlSubjectID => urn:oasis:names:tc:SAML:attribute:subject-id * samlPairwiseID => urn:oasis:names:tc:SAML:attribute:pairwise-id Riferimenti: [[https://wiki.idem.garr.it/wiki/SAML-Subject-ID-Attribute]] Per tutti gli entityID non riferiti al dominio unipr.it occorre concordare il rilascio degli attributi, che saranno filtrati e rilasciati in maniera puntuale da parte del nostro IdP. ===== Istruzioni ===== - Caricare il Metadata dell'IdP, reperibile al paragrafo precedente - Comunicare all'Area Sistemi Informativi il metadata dell'SP via email: - destinatario email: sistemitecnologici.infrastrutture@unipr.it - il metadata può essere comunicato in uno dei seguenti modi: - inserendolo come allegato in formato compresso - indicando l'URL per il download nel corpo del messaggio - Nel caso di entityID non riferito a dominio unipr.it, richiedere gli attributi necessari da rilasciare al vostro SP. - Requisiti: - **Le asserzioni devono essere firmate e cifrate**, pertanto includere in linea nel Metadata del proprio SP i certificati per la firma e la crittografia. ===== Riferimenti ===== * https://shibboleth.atlassian.net/wiki/spaces/SP3/overview?homepageId=2058387896 ====== Protocollo OpenID Connect (OIDC) ====== OpenID Connect Issuer: https://shibidp.unipr.it OIDC Discovery (come da specifiche [[https://openid.net/specs/openid-connect-discovery-1_0.html]]):\\ [[https://shibidp.unipr.it/.well-known/openid-configuration ]] default scope: openid email profile ===== Registrazione relying party (RP) ===== Il gestore del RP deve fornire tutti i redirect URI che verranno registrati lato OP nel Metadata in formato JSON: ^ Nome chiave ^ Tipo del valore ^ Descrizione | | | client_id | string | Identificatore OIDC client per l'RP | fornito da UNIPR | | client_secret | string | Valore alfanumerico che funge da password | fornito da UNIPR | | response_types | array of strings | Tipologia risposte da parte dell'endpoint del OP | id_token (implicit flow) | | scope | string | Lista degli scope che rilasciano i claim | openid email profile spid | | redirect_uris | array of strings | URL di redirezione per la response verso RP | fornito da RP | Esempio: { "redirect_uris":["https://www.esempio.it/secure/redirect_uri"], "client_id":"lamiapp01", "client_secret":"stringaalfanumericasegreta", "response_types":["id_token"], "grant_types":["authorization_code"], "scope": "openid email profile spid" } ^ scope ^ claims - OP identifier ^ claims - oidc names ^ transcoder ^ | openid | subject | sub | OIDCStringTranscoder | | profile | displayName, sn, givenName, codiceFiscale, matricola | name, family_name. given_name, codicefiscale, matricola | OIDCStringTranscoder | | spid | unipr_spid_email, spidName, spidFamilyName, spidCode, spidFiscalNumber, externalIDPLoA, externalIDPType, spid_shib_authnctx_class | unipr_spid_email, spidName, spidFamilyName, spidCode, spidFiscalNumber, externalIDPLoA, externalIDPType, spid_shib_authnctx_class | OIDCStringTranscoder | | email | mail | email | OIDCStringTranscoder | Esempio: ["OIDC_CLAIM_email"]=> string(25) "riccardo.cappone@unipr.it" ["OIDC_CLAIM_spid_shib_authnctx_class"]=> string(30) "https://www.spid.gov.it/SpidL2" ["OIDC_CLAIM_externalIDPLoA"]=> string(4) "LoA3" ["OIDC_CLAIM_family_name"]=> string(7) "CAPPONE" ["OIDC_CLAIM_iat"]=> string(10) "1709631164" ["OIDC_CLAIM_exp"]=> string(10) "1709634764" ["OIDC_CLAIM_name"]=> string(16) "Riccardo CAPPONE" ["OIDC_CLAIM_auth_time"]=> string(10) "1709631164" ["OIDC_CLAIM_spidName"]=> string(8) "RICCARDO" ["OIDC_CLAIM_spidFamilyName"]=> string(7) "CAPPONE" ["OIDC_CLAIM_codicefiscale"]=> string(16) "CPPRCR74P19Z112J" ["OIDC_CLAIM_matricola"]=> string(6) "12345678" ["OIDC_CLAIM_eduPersonScopedAffiliation"]=> string(44) "member@unipr.it staff@unipr.it alum@unipr.it" ["OIDC_CLAIM_aud"]=> string(11) "sptestunipr" ["OIDC_CLAIM_sid"]=> string(33) "_2be7419256300bfc12ae5386638b8287" ["OIDC_CLAIM_spidFiscalNumber"]=> string(16) "CPPRCR74P19Z112J" ["OIDC_CLAIM_nonce"]=> string(43) "I3nOHwGpLWh2whVI-7LBsoPWhxAHo7PEW-VYUuc7GXw" ["OIDC_CLAIM_unipr_spid_email"]=> string(25) "riccardocappone@gmail.com" ["OIDC_CLAIM_given_name"]=> string(8) "Riccardo" ["OIDC_CLAIM_externalIDPType"]=> string(4) "spid" ["OIDC_CLAIM_spidCode"]=> string(14) "NAMI0007649168" ["OIDC_CLAIM_iss"]=> string(24) "https://shibidp.unipr.it" ["OIDC_CLAIM_sub"]=> string(32) "TYFP4PMTLC2VKCSGOCS7QEEPN2I2F4OU" ===== Flusso autorizzativo adottato dal nostro OP ===== response_type => id_token (implicit flow) In questa modalità è attivo solamente l'Authorization Endpoint che dopo l'autenticazione rilascerà l'ID Token comprensivo dei claim sottoscritti dagli scope. La durata dell'ID Token è 1h. {{:guide_pubbliche:howto:identity:response_type_id_token.png?600|}} ===== OIDC client di esempio sviluppato in PhP ===== [[guide_pubbliche:howto:identity:oidc_client|Esempio di OIDC client scritto in PhP]] https://wiki.asi.unipr.it/dokuwiki/doku.php?id=guide_pubbliche:howto:identity:oidc_client \\ \\ \\ ====== Protocollo OpenID Connect (OIDC) via reverse proxy riservato a Relying Party UNIPR ====== Il servizio di autenticazione basato su protocollo OIDC (OpenID Connect via OAuth2) servito via reverse proxy è riservato esclusivamente ai Relying Party UNIPR (su dominio unipr.it). In vista della disattivazione del protocollo CAS, questo middleware semplifica notevolmente l'autenticazione presso il nostro Identity Provider, mettendo a disposizione dei service provider l'intera filiera di autenticazione 'a costo zero', senza cioè il bisogno da parte degli sviluppatori dei servizi web, di gestire il processo di autenticazione. ===== Modalità di richiesta ===== Inviare una richiesta a helpdesk.informatico@unipr.it richiedendo che il proprio servizio web possa avvalersi del middleware di autenticazione OIDC mediato dal reverse proxy UNIPR.\\ Nella richiesta è opportuno indicare se l'intera risorsa debba essere protetta da autenticazione ("/"), oppure solo una o più location specifiche ("/secure", "/percorso/specifico/").\\ Infine indicare anche l'indirizzo IP del backend server (origin server) verso il quale il servizio di reverse proxy eseguirà l'upstream delle richieste.\\ Si ricorda che il reverse proxy effettua TLS offloading, pertanto è obbligatorio accertarsi che il sito di backend non esegua alcun redirect verso https, altrimenti si genera un loop infinito a partire dalla prima richiesta. Quando la richiesta verrà accolta e lavorata, il sito web sarà automaticamente sottoposto ad autenticazione e protetto da certificato TLS. ===== Architettura ===== {{:guide_pubbliche:howto:identity:revproxyoidc.png?direct&800|}} ===== Attributi disponibili post autenticazione ===== ==== Autenticazione con credenziali di Ateneo ==== Headers disponibili [X-Remote-Sub] => TYFP4PMTLC2VKCSGOCS7QEEPN2I2F4OU [X-Remote-Familyname] => ROSSI [X-Remote-Givenname] => Mario [X-Remote-Externalidploa] => LoA2 [X-Remote-Matricola] => 123987 [X-Remote-Codicefiscale] => RSSMAR74P19Z112J [X-Remote-Name] => Mario ROSSI [X-Remote-Email] => mario.rossi@unipr.it In php -> $_SERVER ["HTTP_X_REMOTE_SUB"]=> string(32) "TYFP4PMTLC2VKCSGOCS7QEEPN2I2F4OU" ["HTTP_X_REMOTE_FAMILYNAME"]=> string(7) "ROSSI" ["HTTP_X_REMOTE_GIVENNAME"]=> string(8) "Mario" ["HTTP_X_REMOTE_EXTERNALIDPLOA"]=> string(4) "LoA2" ["HTTP_X_REMOTE_MATRICOLA"]=> string(6) "123987" ["HTTP_X_REMOTE_CODICEFISCALE"]=> string(16) "RSSMAR74P19Z112J" ["HTTP_X_REMOTE_NAME"]=> string(16) "Mario ROSSI" ["HTTP_X_REMOTE_EMAIL"]=> string(25) "mario.rossi@unipr.it" ==== Autenticazione con SPID ==== Headers disponibili [X-Remote-Sub] => TYFP4PMTLC2VKCSGOCS7QEEPN2I2F4OU [X-Remote-Familyname] => ROSSI [X-Remote-Givenname] => Mario [X-Remote-Externalidptype] => spid [X-Remote-Externalidploa] => LoA3 [X-Remote-Codicefiscale] => RSSMAR74P19Z112J [X-Remote-Name] => Mario ROSSI [X-Remote-Email] => mario.rossi@unipr.it In php -> $_SERVER ["HTTP_X_REMOTE_SUB"]=> string(32) "TYFP4PMTLC2VKCSGOCS7QEEPN2I2F4OU" ["HTTP_X_REMOTE_FAMILYNAME"]=> string(7) "ROSSI" ["HTTP_X_REMOTE_GIVENNAME"]=> string(8) "Mario" ["HTTP_X_REMOTE_EXTERNALIDPTYPE"]=> string(4) "spid" ["HTTP_X_REMOTE_EXTERNALIDPLOA"]=> string(4) "LoA3" ["HTTP_X_REMOTE_CODICEFISCALE"]=> string(16) "RSSMAR74P19Z112J" ["HTTP_X_REMOTE_NAME"]=> string(16) "Mario ROSSI" ["HTTP_X_REMOTE_EMAIL"]=> string(25) "mario.rossi@unipr.it" ====== Framework Oauth 2.0 ====== Il framework di autorizzazione OAuth 2.0 consente a un'applicazione di terze parti di ottenere un accesso limitato a un servizio HTTP, sia per conto di un proprietario delle risorse orchestrando un'interazione di approvazione tra il proprietario delle risorse e il servizio HTTP, sia permettendo all'applicazione di terze parti di ottenere l'accesso per proprio conto. OAuth affronta questi problemi introducendo un livello di autorizzazione e separando il ruolo del client da quello del proprietario delle risorse. In OAuth, il client richiede l'accesso alle risorse controllate dal proprietario delle risorse e ospitate dal server delle risorse, e riceve un insieme di credenziali diverso da quello del proprietario delle risorse. Invece di utilizzare le credenziali del proprietario delle risorse per accedere alle risorse protette, il client ottiene un token di accesso - una stringa che denota uno specifico ambito, durata e altri attributi di accesso. I token di accesso vengono rilasciati ai client di terze parti dai nodi del cluster Shibboleth (server di autorizzazione) con l'approvazione del proprietario delle risorse. Il client utilizza il token di accesso per accedere alle risorse protette ospitate dal server delle risorse. Per approfondire si prega di consultare: [[https://www.rfc-editor.org/rfc/rfc6749.html]] ===== Flusso di autenticazione ===== - **Richiesta di Autorizzazione**: L'utente avvia il processo cliccando su un pulsante o un link all'interno dell'applicazione client. Questo reindirizza l'utente al server di autorizzazione, dove gli viene richiesta l'autenticazione e di conseguenza autorizza il client ad accedere a specifiche risorse dell'utente presenti su di un server di risorse. - **Concessione dell'Autorizzazione**: Il server di autorizzazione verifica l'identità dell'utente e genera un codice autorizzativo (Auth Code) da utilizzare per richiedere un nuovo token di accesso ed un refresh_token. Viene emesso anche un id_token (contenente i claim riferiti all'utente) ed un primo access_token. - **Accesso alle Risorse**: L'applicazione client utilizza il token di accesso per fare richieste al server delle risorse. Il server delle risorse verifica il token e, se valido, concede l'accesso alle risorse richieste. - **Utente ottiene visibilità della risorsa richiesta**: L’applicazione può mostrare all’utente le risorse recuperate dal Server Risorse. {{ :guide_pubbliche:howto:identity:sequence_diagram_01.png?direct&800 |}} ===== Validità temporale dei token ===== ^ tipo token ^ Durata ^ | Auth Code | 5 minuti | | Access token | 10 minuti | | Refresh token | 120 minuti | | ID token | 60 minuti | ===== Informazioni del server di autenticazione/autorizzazione ===== OpenID Connect Issuer: https://shibidp.unipr.it OIDC Discovery (come da specifiche [[https://openid.net/specs/openid-connect-discovery-1_0.html]]): [[https://shibidp.unipr.it/.well-known/openid-configuration]] Questo URI consente di ottenere l informazioni principali contenute nel Metadata dell'OP Server di autenticazione/autorizzazione, come ad esempio l'Authorization Endpoint, il token Endpoint, l'introspection Endpoint, etc. __Specifiche OAuth2 implementate e supportate__: * RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage * RFC 7636: Proof Key for Code Exchange by OAuth Public Clients * RFC 8707: Resource Indicators for OAuth 2.0 * RFC 9068: JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens * RFC 7662: OAuth 2.0 Token Introspection ===== Ruoli ===== E' necessario identificare gli attori coinvolti. **Client** è l'applicazione che richiede l'accesso alle risorse protette ospitate su un server di risorse. Il Client agisce per conto dell'utente (proprietario delle risorse) e deve ottenere un token di accesso dal server di autorizzazione per poter accedere a tali risorse. Il Client non utilizza direttamente le credenziali dell'utente, ma opera con i token di accesso rilasciati dal server di autorizzazione. Al Client verranno rilasciate le seguenti informazioni: * client_id * client_secret * resource indicator (parametro obbligatorio nella request autorizzativa) il parametro resource richiesto dal client, sarà utilizzatto come audience nei token che verranno rilasciati. Questo valore di audience sarà verificabile solamente dal Server della risorsa che avrà il corrispondente client_id (e client_secret) per verificarlo via introspezione. Il client deve effettuare la request autorizzativa verso il server di autorizzazione richiedendo obbligatoriamente: * response_type=code token id_token * redirect_uri= * scope=openid profile email spid offline_access * resource= Il metodo di autenticazione da utilizzare quando il Client si autentica con il Server autorizzativo è client_secret_basic (credenziali vengono inviate nell'intestazione di autorizzazione come una stringa codificata in base64) Esempio di request usando PKCE: {{ :guide_pubbliche:howto:identity:initial_requsest.png?direct&600 |}} **Server della risorsa** è il server che ospita le risorse protette a cui il Client desidera accedere. Il ruolo principale del Server di risorsa è quello di gestire e proteggere l'accesso a queste risorse. Quando un Client richiede l'accesso, il Server di risorsa verifica la validità del token di accesso fornito dal Client, spesso consultando il Server di autorizzazione per confermare che il token sia valido e non scaduto. Se il token è valido, il Server di risorsa concede l'accesso alle risorse richieste. Al server della risorsa verranno rilasciate le seguenti informazioni: * client_id * client_secret Il metodo di autenticazione da utilizzare quando il Server della risorsa si autentica con il Server autorizzativo è client_secret_post (client_id e client_secret come parametri aggiuntivi nel corpo della richiesta POST al token di introspezione) Esempio di request all'introspection endpoint: {{ :guide_pubbliche:howto:identity:introspection_call.png?direct&600 |}} Esempio response caso token non valido: {{ :guide_pubbliche:howto:identity:introspection_failed.png?direct&200 |}} Esempio response caso token valido: {{ :guide_pubbliche:howto:identity:introspection_ok.png?direct&300 |}} ===== Utilizzo dell'Auth Code ===== Il Client può utilizzare l'Auth Code per ottenere: * access_token * refresh_token * id_token Esempio di request utilizzando l'Auth Code: {{ :guide_pubbliche:howto:identity:auth_code_request.png?direct&600 |}} ===== Utilizzo del refresh_token ===== Il Client può utilizzare il refresh_token per ottenere: * access_token * refresh_token Esempio di request utilizzando un refresh_token: {{ :guide_pubbliche:howto:identity:refresh_token_request.png?direct&600 |}} {{ :guide_pubbliche:howto:identity:refreeh_aut_code_requests.png?direct&800 |}}