427 messaggi dal 13 novembre 2009
Salve,
apro una richiesta specifica. Ho piu siti, un dominio e tanti sottodomini
www.dominio.it
www.sito1.dominio.it
www.sito2.dominio.it

In ognuno aspnetcore ho implementato lo shared cookie auth con persistenza della chiave ecc...Tutto funziona.
Di default ho utilizzato identity per la generazione del database su SQL Server a cui tutti i siti puntano.
La logica prevede che ciascun sito però abbia una gestione differente dei ruoli. In base al ruolo specifico puoi o meno andare su parti del sito naturalmente.
Il sito1 prevede Admin, Manager, Agent
Il sito2 prevede Admin, Advisor, Rep
Quindi se Admin è il medesimo, gli altri cambiano.
Nel ApplicationDbContext ho implementato solo IdentityUser.
I due siti hanno database differenti avendo attività differenti.
Morale...volendo creare una tabella dei Ruoli nei singoli database e volendo implementare Autorize su i controller come farlo?

grazie
427 messaggi dal 13 novembre 2009
Mi spiego meglio...Utilizzando il defaultauth applicationdbcontext comunque contiene la gestione anche dei ruoli.
Lo scopo è quello che creare una autenticazione unica per dominio e sottodomini e tenere a parte i ruoli in ciascun database del sottodominio. Ogni sottodominio ha i propri ruoli.
alla chiamata tramite jwtbearer o cookie del sottodominio scatta l'attributo Autorize, ma qui il problema.
Innagino che debba creare un customauthattribute e decorare il controller. All'interno dell'attributo fa la retrieve dei ruoli dell'utente loggato e verificare se puoi chiamare il controller (web o api)
F.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Flavio,
ecco una possibile soluzione che dovrebbe darti più flessibilità:
  • NON creare i ruoli così generici come Admin, Manager, Agent. Crea invece dei ruoli più granulari possibile, chiamati ad esempio "Customer.Read", "Customer.Create", "Customer.UpdateBankInfo", "Customer.AssignToEmployee", ...
  • Poni l'attributo Authorize sulle action, indicando il ruolo (o i ruoli) necessari alla sua esecuzione.
    [Authorize(Roles = "Customer.Create")]
    public IActionResult CreateCustomer()
    {
      //...
    }
    
  • Ora creati una nuova tabella chiamata ad esempio "Profiles" in cui inserisci Admin, Manager, Agent. Ciascuno di essi sarà relazionato a una moltitudine di ruoli. Ad esempio il profilo "Admin" sarà relazionato a tutti i ruoli, ma per un altro tenant potrebbe non essere così se per esempio lì è previsto anche un "SuperAdmin";
  • NON relazionare gli utenti ad alcun ruolo. Nel cookie di autenticazione ci metti invece il claim che indica il profilo a cui è assegnato;
  • Ti crei un middleware personalizzato che usi subito dopo quello di autenticazione. Lo scopo di questo ruolo sarà quello di leggere l'identità e ottenere da essa il nome profilo (Es. Admin) e di aggiungere ad essa tutti i claim dei ruoli associati a quel profilo. Usa il servizio IMemoryCache per evitare di dover recuperare l'elenco dei ruoli dal database ad ogni richiesta.



Questa tecnica la puoi ovviamente attuare in tanti altri modi, ad esempio scrivendo un AuthorizeAttribute personalizzato. Vedi tu cosa ti conviene fare.

ciao,
Moreno

Enjoy learning and just keep making
427 messaggi dal 13 novembre 2009
In pratica tu dici di crearmi un middleware che tramite ti i li username (univoco) recuperi i ruoli utente i li inietti come claim. Questi sono alla base di Authorize(Roles...)
Due domande:
new Claim(CustomClaimTypes.Permission, "Customer.Create") giusto?
Ma tu dici di passare in fase di login i claims? O di iniettarli ad ogni richiesta?
Considera che la cosa dovrà funzionare sia scon i cookie sia con jwtbearer, questultimo per chiamate rest all'interno dello stesso sito.
Infine, non vorrei utilizzare entityframework codefirst per creare applicationdbcontext, ma un manager scritto da me come versione semplificata.
Ci sarà un database con tabelle di autenticazione e tabelle ruoli e profili. I profili hanno un campo che riconduce al sottodominio. Quindi ci sarà
ID 1 Profile Admin Domain www.domain.it
ID 2 Profile Manager Domain www.domain.it
---
ID 3 Profile Admin Domain www.site1.domain.it
---
ID 3 Profile User Domain www.site2.domain.it
---
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


In pratica tu dici di crearmi un middleware che tramite ti i li username (univoco)

Sì, puoi anche associare i ruoli all'utente senza creare alcun "Admin", "Manager" e così via. In questo modo puoi avere una configurazione di ruoli personalizzata per utente.

Io però penso che qualche archetipo di profilo (es. "Admin") il tuo tenant lo vorrà avere, almeno per impostare velocemente un insieme di ruoli di partenza. Poi il tuo tenant potrebbe aggiungerli o toglierli a piacimento senza essere vincolato da ciò che è previsto dall'archetipo.

...ammesso che tu voglia consentire al tuo tenant di arrivare a questo livello di personalizzazione per utente. Altrimenti gli fai impostare un profilo (Es. "Admin") e basta.


recuperi i ruoli utente i li inietti come claim.

Sì, perché i ruoli sono molto specifici (es. "Customer.Create") e finirai per averne una marea. Infilarli tutti nel cookie di autenticazione sarebbe certamente possibile, ma se ogni utente ne ha a centinaia, il cookie potrebbe diventare grandino e arrivare fino al suo limite fisico di 4KB. Qui devi valutare tu: se hai pochi ruoli e riesci a restare ben sotto la soglia dei 4KB, li puoi infilare direttamente nel cookie (e nel token) come claim e non ci sarà bisogno di crearsi un middleware che li vada a pescare dal database (o dalla cache).

new Claim(CustomClaimTypes.Permission, "Customer.Create") giusto?

No, aggiungilo come ClaimTypes.Role, così potrai sfruttare l'attributo [Authorize(Roles="Customer.Create")].
Oppure ti crei un attributo Authorize personalizzato.

Ma tu dici di passare in fase di login i claims? O di iniettarli ad ogni richiesta?

Come dicevo qui sopra: se sono pochi puoi metterli direttamente nel cookie. Se sono tanti non ci metti nulla e poi però dovrai recuperarli ad ogni richiesta dalla cache in base all'utente o al suo profilo (es. "Admin"). Questa sarà un'operazione rapida se sfrutti la cache.


entityframework codefirst per creare applicationdbcontext

Se non vuoi usare EFCore ok, ma non rinunciare ad ASP.NET Core Identity perché ha tante funzionalità di sicurezza che renderanno sicuri i dati dei tuoi utenti. Ecco come realizzare uno user store personalizzato (ma non sarà la cosa più semplice di questo mondo).
https://docs.microsoft.com/it-it/aspnet/core/security/authentication/identity-custom-storage-providers?view=aspnetcore-2.2#customize-the-user-store

ciao,
Moreno

Enjoy learning and just keep making
427 messaggi dal 13 novembre 2009
Buongiorno,
in realtà la cosa è piu "semplice". Non ho ruoli all'interno dell'intero sistema fatto di dominio e sottodomini. L'utente ha un profilo e con quello agisce sulle tabelle di gestione insert/update/delete ecc..
Solo l'admin vede quelle tabelle readonly, ma agisce in maniera esclusiva sulla parte di censimento e configurazione utenze e dati primitivi. Quindi opterei per la sol tabella Profile.
Detto questo ho un problema di fondo.
I sottodomini rappresentano i clienti e quindi una utenza del cliente dovrebbe accedere solo al dominio principale e al sottodominio di competenza che poi è il sito dell'azienda.
Quindi l'idea e le domande:
- un unico database con dbo.Utenti e dbo.Profile generico per tutti?
- nello stesso database lavorando con gli schemi: cl1.Articoli, cli2.Articoli. Questo significa che l'utenza Mario se loggato al sito cl1 quando da quello fa una richiesta il datamodel referenziato dal sito userà lo schema cl1.
Quindi non mi deve preoccupare di controllare se MArio può utilizzare il datamodel cl1 perché se accede e lavora sul sottodominio cl1 allora in automatico utilizzarà il datamodel che fa riferimento allo schema cl1.
Lavorando con gli schemi quindi avrei innanzitutto un solo database e non un database per le sole utenze e tanti database per ciascun sottodominio.
Come faccio però a fare in modo che Mario loggandosi sul dominio principale abbia un cookie che lavori solo per dominio.com e cl1.dominio.com?
Volendo utilizzare CookieAuthenticationOptions CookieDomain come faccio a prevedere l'accesso solo a dominio.com e site1.dominio.com?
CookieAuthenticationOptions CookieDomain prevede accesso a tutto ciò che finisce con .dominio.com
In pratica:
Mario ha accesso a dominio.com e site1.dominio.com
Luca ha accesso a dominio.com e site2.dominio.com
Ovviamente in fase di login e due dovranno essere loggati in automatico ai rispettivi siti. In Aspitalia viene adottato il meccanismo di passare le grant ai vari sottodomini e non vorrei farlo nemmeno in ajax dovendo abilitare CORS. Sarebbe interessante capire come prevedere nella configurazione di ogni sito la possibilità di specificare in CookieDomain= "dominio.com,sitex.dominio.com"

p.s.
ho trovato forse la soluzione?
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "cl1.dominio.com",
CookieDomain = "cl1.dominio.com",
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "dominio.com",
CookieDomain = "dominio.com",
});

Questo in ogni sottodominio, dando dunque accesso per quel sottodominio anche al dominio.
Ma così l'utente si logga solo dal sottodominio. Se si logga dal dominio dovrei creare dinamicamente i cookie? Come? Una parte della soluzione sarebbe quella di censire nel database una tabella di collegamento tra utenza e schemi così che a Mario venga associato lo schema cl1, ma poi come creare dinamicamente il cookie relativo al sottodominio il cui nome corrisponde allo schema (cl1) quando l'utente si logga?

oppure qualcosa del genere
app.UseCookieAuthentication(options =>
{
options.AuthenticationType = "type1";
options.CookieName = "type1";
});

app.UseCookieAuthentication(options =>
{
options.AuthenticationType = "type2";
options.CookieName = "type2";
});

E nel controller
Response.SignIn(new ClaimsIdentity("type1"));
Response.SignIn(new ClaimsIdentity("type2"));
Modificato da flaviovb il 26 luglio 2019 09:24 -
11.886 messaggi dal 09 febbraio 2002
Contributi

specificare in CookieDomain= "dominio.com,sitex.dominio.com"

Non è possibile farlo. La specifica non lo prevede.
https://tools.ietf.org/html/rfc6265#section-5.1.3


Mario ha accesso a dominio.com e site1.dominio.com
Luca ha accesso a dominio.com e site2.dominio.com

Puoi fare come Aspitalia e reindirizzare l'utente verso tutti i domini a cui ha accesso, in modo da emettere un cookie per ciascun dominio.
Oppure emetti un cookie per .dominio.com che coprirà anche i sottodomini. Se Mario naviga su site2.dominio.com, risulterà autenticato ma non potrà comunque vedere nulla perché lo bloccherai a livello di autorizzazione perché tra i suoi claim non ci sarà quello che gli consente di visitare site2.dominio.com.

ciao,
Moreno

Enjoy learning and just keep making
427 messaggi dal 13 novembre 2009
Direi che è preferibile come aspitalia. Mi domando come? Fare la redirect a site1.dominio.com a quale action? e con quali parametri?
Mario non deve entrare in site2.dominio.com da autenticato, sebbene io possa poi verificare con authorizeattribure che Mario nel suo set di schema non ha site2 ma solo site1
F.
Modificato da flaviovb il 26 luglio 2019 10:05 -

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.