657 messaggi dal 13 novembre 2008
Contributi
ciao,
uso il servizio Identity in una applicazione multitenant (webapp su Azure mappata a dominio custom)
facendo l'accesso al dominio principale il cookie di identità è disponibile anche ai sottodomini grazie a questa configurazione

services.AddIdentity<..>(
config =>
{
config.Cookies.ApplicationCookie.CookieDomain = ".domain.com";
...

funziona dunque per

www.domain.com
site1.domain.com
site2.domain.com
site3.domain.com
...


adesso è nata l'esigenza di mappare i sottodomini a domini custom; il mio scopo è quello di mantenere l'autenticazione sul dominio principale dell'app www.domain.com e rendere il cookie di identità disponibile anche ai domini custom, per es. www.otherdomain.com mappato a site1.domain.com

come posso fare mantenendo l'attuale sistema?
grazie!
11.868 messaggi dal 09 febbraio 2002
Contributi
Ciao,
se l'utente si autentica dalle pagine di www.dominio.com, lato server non potrai emettere un cookie per www.altrodominio.com. E' una questione di sicurezza: il browser rifiuta il cookie se viene indicato un dominio diverso da quello su cui sta navigando l'utente.

Questo problema si è posto anche qui su Aspitalia, dato che il network è formato da vari altri domini come windowsazureitalia.com, linqitalia.com e html5italia.com. Se fai caso a come è stato risolto, noterai subito dopo aver messo le tue credenziali, vieni reindirizzato in ciascuno di quei domini affinché abbiano l'opportunità di emettere un cookie per quel particolare dominio.
Puoi provare a rendere la cosa un po' più discreta effettuando richieste ajax anziché ridirezioni (dovrai abilitare CORS, però).

Inoltre, togli questa impostazione:
config.Cookies.ApplicationCookie.CookieDomain = ".domain.com";


L'alternativa consiste nell'usare un meccanismo di single sign-on.
http://www.aspitalia.com/articoli/asp.net/single-sign-on-identity-server.aspx

ciao,
Moreno

Enjoy learning and just keep making
657 messaggi dal 13 novembre 2008
Contributi
ciao, infatti, il problema è il rifiuto del cookie che proviene da un dominio differente; sia un sistema di SSO tipo identity server, sia un sistema basato sui token (OpenIddict) sono al momento onerosi in quanto ho già tutto un sistema custom di identity funzionante
comunque, siccome sembra semplice ma io ho un vuoto totale qui

dopo aver messo le tue credenziali, vieni reindirizzato in ciascuno di quei domini affinché abbiano l'opportunità di emettere un cookie per quel particolare dominio


come lo implemento?

--------------

update..

ho provato, perché interessante, una implementazione con OpenIddict, creando un controller di autorizzazione del tipo
[HttpPost("~/connect/token")]
public async Task<IActionResult> Exchange()
{...
...verifiche su user..
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}

facendo una richiesta con Postman, con nel body user e password, ottengo il mio Bearer access_token

------

ora, sia col primo metodo, sia con OpenIddict, l'utente entra nel dominio principale, inserisce i dati di login, i dati arrivano nel controller Account action Login dove normalmente avviene il signIn così

var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);


qui invece adesso devo recuperare il dominio custom dell'utente (mappato ad un sottodominio dell'app principale) e fin qui ok, generare il token (con openIddict faccio una WebRequest per es.) o il cookie (come?), fare in modo che il dominio custom lo veda per poter autenticare l'utente anche li

come fare però, sia nel caso scegliessi la soluzione basata sul token sia per il cookie?


grazie ancora.
Modificato da teo prome il 02 novembre 2016 14.23 -
11.868 messaggi dal 09 febbraio 2002
Contributi
Ciao,


sia nel caso scegliessi la soluzione basata sul token sia per il cookie?

Per il token non ci sono problemi. Se il tuo client è una single page application o un'app mobile, il token gli può arrivare da un dominio qualsiasi e l'app può scegliere di reinviarlo anche ad un dominio diverso. Infatti è l'app stessa che si fa carico di ricevere il token, memorizzarlo da qualche parte e reinviarlo come intestazione in ogni successiva richiesta.

Il problema si pone invece per i cookies, dato che è il browser a decidere come e quando reinviarlo nelle successive richieste. Bisogna accettare il fatto che i cookies non sono cross-domain e che devi perciò emetterne uno per dominio.

sembra semplice ma io ho un vuoto totale qui

Puoi fare così: dopo aver verificato che l'utente ha inserito le credenziali corrette grazie al PasswordSignInAsync, creati un Guid che identifichi questa specifica azione di login. Memorizza il guid in una tabella del database insieme al nome utente che si è loggato e insieme al nome a dominio alternativo. Se vuoi maggiore sicurezza, mettici anche una data/ora di scadenza.
Fatto questo, reindirizza verso l'altro dominio, ad un'action apposita a cui passerai il guid come parametro querystring.
Questa action leggerà il guid dalla querystring ed andrà a cercarlo nella tabella in cui l'aveva inserito prima. Filtra anche per il nome a dominio come criterio di ricerca ed estrai il nome utente.
Usa il nome utente nel metodo SignInAsync del SignInManager, in modo che venga emesso il cookie di autenticazione.
Elimina dalla tabella la riga che reca il Guid e il nome a dominio attuali, in modo che non possa essere riutilizzata in futuro.
Se nella tabella ci sono altre righe che recano lo stesso Guid, reindirizza verso il prossimo nome a dominio, altrimenti reindirizza l'utente all'homepage.

ciao,
Moreno

Enjoy learning and just keep making
657 messaggi dal 13 novembre 2008
Contributi
ciao, per i cookie ora mi è chiaro
per il token ancora dubbi:

da user e password genero un json che ha
"token_type": "Bearer",
"access_token": "..", (circa 1000 caratteri)
"expires_in": 1800,
"id_token": "..." (circa 1000 caratteri)

dopo aver generato l'access_token al login, devo comunque memorizzarlo? altrimenti come posso passarlo direttamente ad un altro dominio?

una volta che il dominio custom ha ricevuto il token posso poi impostare li un header del tipo

using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("...");
}
in modo da non dover inviare il token ad ogni successiva richiesta?

grazie.
657 messaggi dal 13 novembre 2008
Contributi
ciao, ho implementato la soluzione con i cookies e funziona, in parte, per le mie esigenze:
l'utente si logga su domain.com, viene autenticato su tenant.domain.com, se ha un dominio custom viene autenticato su pippo.com

ovviamente questa soluzione funziona eliminando
//config.Cookies.ApplicationCookie.CookieDomain = ".domain.com"
dalla configurazione del servizio Identity

questo però crea un problema:

supponiamo che l'utente tenant1 debba interagire con una pagina riferita ad un altro tenant tenant2, per esempio deve inserire un commento nella pagina principale di tenant2
va su
tenant2.domain.com
ma ovviamente qui non esiste il cookie di autenticazione, quindi il post protetto da [Authorize] non permette l'inserimento....

quindi in realtà al login io dovrei emettere un cookie su .domain.com e non tenant1.domain.com e, se l'utente ha un dominio custom, anche su pippo.com; ma si può scrivere il cookie domain a runtime?

che soluzione posso adottare per gestire questa situazione?

grazie!
Modificato da teo prome il 07 novembre 2016 09.25 -
11.868 messaggi dal 09 febbraio 2002
Contributi
Ciao,


per esempio deve inserire un commento nella pagina principale di tenant2

Se i commenti sono aperti a tutti gli utenti (purché autenticati), allora il form di commento potrebbe puntare ad un'action su www.domain.com, cioè il dominio principale per il quale tutti gli utenti possiedono il cookie di autenticazione.

Se no, se devi poter decidere chi può fare cosa tra vari tenant, vai di single sign-on.
http://www.aspitalia.com/articoli/asp.net/single-sign-on-identity-server.aspx

ciao,
Moreno

Enjoy learning and just keep making
657 messaggi dal 13 novembre 2008
Contributi
ok, si l'idea è buona, non immediata però da costruire....

la sezione commenti è costruita con un modello MVVM, quindi effettuo chiamate ajax per le varie azioni di GET e POST; ora, dato che l'idea è di richiamare le action sul dominio principale da sottodomini o domini custom dovrei:

1) abilitare CORS per quelle action
creo uno policy
dato che non so quale dominio chiamerà la action, e dato che a quanto ne so non è possibile (per ora?) settare a runtime CORS su un dominio specifico (e abilitarlo su tutti su startup sarebbe impensabile) lo configuro settando

AllowAnyOrigin() e AllowCredentials();

2) permettere alle chiamate ajax di inviare le credenziali
... withCredentials: true ...

3) mettere gli attributi sulle action
[Authorize]
[HttpPost]
[EnableCors("Allow")]

ora, sembrerebbe terminato, ma così chiunque potrebbe effettuare chiamate a quelle actions da un qualsiasi dominio, e se riuscisse ad inviare delle credenziali sarebbe un problema; quindi devo anche creare un meccanismo di controllo del tipo: chi chiama è abilitato a farlo?

4) ho pensato quindi ad un actionFilter che verifichi
a. che l'host che fa la richiesta sia il mio dominio principale
b. che l'origine della richiesta corrisponda ad una origine (cioè dominio custom o sottodominio) presente in una risorsa della mia app (db, table o altro)

5) aggiungere l'attributo relativo all'actionFilter creato [ActionFilterCorsOrigin]

a logica dovrebbe andare e soprattutto non devo implementare un diverso sistema di sign-on :)

che ne pensi Moreno?

grazie e ciao.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.