Moet altijd alles een moderne SPA zijn?

Pagina: 1 2 3 Laatste
Acties:

Acties:
  • 0 Henk 'm!

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 23-09 14:00
Jantje2000 schreef op maandag 30 september 2019 @ 16:01:
[...]

Ja, angular heeft ook mijn voorkeur inderdaad, omdat ik dan het meest nieuw leer.

OAuth laat ik nu inloggen, door de gebruiker na een klik op de button, een popup te geven die via de server naar Google redirect. Dan log je in, waarna de server jouw oauth gegevens ontvangt. Op basis van die gegevens verstrek ik een jwt token aan de client, waarna de client daarbij kan blijven authenticeren

Api bouwen met .Net Core is heel erg gemakkelijk, het lastigste blijft de authenticatie :P. Dat moet gelijk goed gebeuren
Aangezien je (ASP).NET Core is het handig om Microsoft: Overview of ASP.NET Core Security door te nemen. Daar staat beschreven hoe je het kunt combineren met een SPA en hoe je external logins (zoals Google, Microsoft, Facebook, e.d.) toevoegt.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Jantje2000 schreef op maandag 30 september 2019 @ 16:04:
Als ik dan dus laten expiren na 10 minuten, heb je dan ook nog weer speciale refreshtokens nodig?
Nee, een refresh kan prima met je huidige token. Je wisselt dus je huidige token in voor een nieuw token.
En zou jij een ander token dan jwt aanraden, of maakt dat ook weer niet heel erg veel uit?
Ik had in deze opzet geen JWT gebruikt voor een 'echte' productie service omdat mijn doel vooral is shit zo simpel mogelijk te houden. Maar je bent stagair dus jouw doel is vooral om zoveel mogelijk te leren. Dus ik zou het lekker met JWTs laten :)

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
Die security overview en de api authorization heb ik gebruikt inderdaad, echter is de pagina voor external logins uitsluitend gericht op MVC Core, zonder SPA dus. Dat is dan ook het lastigste stukje
Hydra schreef op maandag 30 september 2019 @ 16:09:
[...]


Nee, een refresh kan prima met je huidige token. Je wisselt dus je huidige token in voor een nieuw token.


[...]


Ik had in deze opzet geen JWT gebruikt voor een 'echte' productie service omdat mijn doel vooral is shit zo simpel mogelijk te houden. Maar je bent stagair dus jouw doel is vooral om zoveel mogelijk te leren. Dus ik zou het lekker met JWTs laten :)
Duidelijk. Bedankt voor je adviezen!

[ Voor 23% gewijzigd door Jantje2000 op 30-09-2019 16:11 ]

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 23-09 14:00
Jantje2000 schreef op maandag 30 september 2019 @ 16:09:
[...]

Die security overview en de api authorization heb ik gebruikt inderdaad, echter is de pagina voor external logins uitsluitend gericht op MVC Core, zonder SPA dus. Dat is dan ook het lastigste stukje
Je hebt een stap hoe je ASP.NET Identity gebruikt met een SPA, en hoe je external logins toevoegt aan ASP.NET Identity. Maar die kun je gewoon samen gebruiken. Het is niet alsof externe logins anders behandeld worden zodra ze ingelogd zijn, ze krijgen gewoon een sessie/token, e.d.

Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
ThomasG schreef op maandag 30 september 2019 @ 16:16:
[...]
Je hebt een stap hoe je ASP.NET Identity gebruikt met een SPA, en hoe je external logins toevoegt aan ASP.NET Identity. Maar die kun je gewoon samen gebruiken. Het is niet alsof externe logins anders behandeld worden zodra ze ingelogd zijn, ze krijgen gewoon een sessie/token, e.d.
Ja dat klopt inderdaad. Ik heb het ook op die manier gecombineerd, door een popup te geven die wel gewoon op de server staat. Die haalt de OAuth gegevens op, waarna op basis daarvan een jwt token wordt gegenereerd

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • ard1998
  • Registratie: December 2015
  • Laatst online: 09-06 19:59
Hydra schreef op maandag 30 september 2019 @ 13:26:
[...]

Ik snap echt niet hoe je dat allemaal uit jwt.io haalt. Je hele verhaal slaat als een tang op een varken.
Daarnaast snap ik ook niet zo goed waarom je in een gesprek mengt na even vluchtig een pagina bekeken te hebben. Wat schiet iemand hier mee op?

Schaalbaarheid is veruit het belangrijkste voordeel van JWTs.

[...]


Dit klinkt alsof je JWT en OAuth door elkaar haalt.
Alseerst, een protocol is ter standaardisatie. De implementatie is hetgeen dat schaalbaar kan zijn.

Zelf ben ik het sterk eens met het artikel van Eran Hamme https://hueniverse.com/oa...road-to-hell-8eec45921529 met. Kort samengevat: Een paar grote bezrijven die de kracht van een authenticatiemethode onderuit halen door de grote pluspunten weg te halen, een systeem met tijdelijke tokens in te stellen om rondom de gecreerde zwakte te werken en dat als good practice aan te bieden. daarnaast een 71 pagins's dik document met oauth2 zwaktes omdat er in de wekgroep over veel belangrijke onderwerpen geen concrete besluiten genomen werden (https://tools.ietf.org/html/rfc6819#page-47). Maar zelf heb ik ook meer dingen waarvan ik vind dat we te veel naar de touwtjes van de grote bedrijven spelen ten koste van de kwaliteit en/of structuur van de projecten.

Wat dat betreft zie ik 1 valiede usecase voor JVT, beveiligen van de authenticatieoverdracht. naar jezelf of naar een derde partij. stop de authenticatiecode in een libary en het maakt het niet uit of het nou SPA of MPA is. schrijf een systeem dat de login / tokengenatie verzorgt en dat dat in een libary of gebruik een libary van een derde partij die je gebruikt bij iedere paginaaanroep. eventueel kan er jwt gebruikt worden. dus doe het dan op z'n minst goed met een MPA. scheelt een hoop onnodige downoad en het maakt de website beter navigeerbaar voor iedereen, ook dezene die gebruik moeten maken van acessabillity tools. Als je toch goed bezig ben, vervand de "ik ben een frontend developer en kan aleen maar met frameworks werken" code en versimpel je backend door de "ik haat sql en database ontwerpen, dus ik gooi er tig lagen abstractie tussen" te vervangen door nette sql oplossingen op basis van een database ontwerp . Dit functioneert als je database structuur en zijn documentatie.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Je begint weer over OAuth terwijl we het over JWT hadden. Heb verder weinig trek in een hoop random gezwets te moeten beantwoorden, sorry.

[ Voor 32% gewijzigd door Hydra op 30-09-2019 17:46 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • ard1998
  • Registratie: December 2015
  • Laatst online: 09-06 19:59
Hydra schreef op maandag 30 september 2019 @ 13:26:
[...]


Ik snap echt niet hoe je dat allemaal uit jwt.io haalt. Je hele verhaal slaat als een tang op een varken.
Daarnaast snap ik ook niet zo goed waarom je in een gesprek mengt na even vluchtig een pagina bekeken te hebben. Wat schiet iemand hier mee op?

Schaalbaarheid is veruit het belangrijkste voordeel van JWTs.


Dit klinkt alsof je JWT en OAuth door elkaar haalt.
Hydra schreef op maandag 30 september 2019 @ 17:45:
[...]


Je begint weer over OAuth terwijl we het over JWT hadden. Heb verder weinig trek in een hoop random gezwets te moeten beantwoorden, sorry.
Zegt degeen die in eerste instantie Oath in de mond nam waarop ik reageer met dat ik me niet daarin vergis want ... en ik zie het gebruik van JWT in de volgende context. Ja, mijzelf zuidelijk maken is niet mijn sterkste punt, dat weet ik ;)

Acties:
  • +3 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
@Jantje2000 @Hydra Het is mij gelukt om een Angular SPA te laten inloggen op een .NET Core API met simpelweg cookie authentication :)

Het .NET Core framework beheert dan de sessie voor mij. Ik moest met de volgende zaken rekening houden:
  • De Angular app doet zijn requests met de withCredentials optie. Authenticeren gaat gewoon door een POST te doen op een /api/auth/authenticate met credentials.
  • Nadat ik de credentials heb gecontroleerd, laat ik het .NET Core framework een cookie maken door HttpContext.SignInAsync aan te roepen ( https://docs.microsoft.co...ookie?view=aspnetcore-3.0 ).
  • In mijn Angular router module gebruik ik een guard die een GET request doet op /api/auth/check. Krijg ik een 401 terug, dan navigeer ik naar het LoginComponent:
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuardService implements CanActivate {
    
      constructor(private backend: BackendService, private router: Router) { }
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
        return this.backend.authCheck().pipe(
          map(result => { 
            if (result) return true;
            this.router.navigate(['/login']);
          })
        );
      }
    }

    En de code in de BackendService:
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    
      authCheck(): Observable<boolean> {
        let url = `${this.backendUrl}/api/auth/check`;
    
        return this.http.get(url, { withCredentials: true }).pipe(
          map(data => true),
          catchError(err => of(false))
        );
      }

    Hier zou ik nog wat meer error handling kunnen doen, dat ik echt naar een 401 kijk, zodat de sessie niet verbroken wordt door andere communicatiefouten.
  • Ik moest .NET Core wel even vertellen dat hij een 401 moet geven en niet moet proberen naar een eigen login pagina te redirecten.
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
          services
            .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
              options.Events.OnRedirectToLogin = (context) =>
              {
                context.Response.StatusCode = 401;
                return Task.CompletedTask;
              };
            });
  • Uiteraard gaat alles via HTTPS.
  • Ik moest de Cookie policy nog aanpassen, zodat de cookie HttpOnly, SameSite en ook Secure zijn:
    code:
    1
    2
    3
    4
    5
    6
    7
    
          var cookiePolicyOptions = new CookiePolicyOptions
          {
            MinimumSameSitePolicy = SameSiteMode.Strict,
            HttpOnly = HttpOnlyPolicy.Always,
            Secure = CookieSecurePolicy.SameAsRequest // Voor development
          };
          app.UseCookiePolicy(cookiePolicyOptions);
  • ASP.NET Core versleutelt automatisch de cookie voor mij (ASP.NET Core Data Protection). Mocht ik in de toekomst ooit moeten load balancen, dan is het mogelijk om meerdere instanties dezelfde key ring te laten gebruiken, zodat alles blijft werken (al ga ik er niet vanuit dat dit ooit nodig is voor dit project).
Overwegingen om voor cookie auth te kiezen:
  • Schaalbaarheid is geen issue voor dit project. Het vervangt een oude management console die al 10 jaar lang op 1 server gehost werd. Het project wordt nieuw leven ingeblazen, maar zal naar alle waarschijnlijkheid zelfs minder users hebben dan de oude console ooit had (50 tot 100 geprojecteerd).
  • Het is veel simpeler in te bouwen dan een JWT based auth met IdentityServer etc.
  • Het is mogelijk een sessie te killen.
Mochten jullie nog op- en aanmerkingen hebben, graag :)

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • GrooV
  • Registratie: September 2004
  • Laatst online: 10:00
Lethalis schreef op maandag 30 september 2019 @ 22:05:
@Jantje2000 @Hydra Het is mij gelukt om een Angular SPA te laten inloggen op een .NET Core API met simpelweg cookie authentication :)

Het .NET Core framework beheert dan de sessie voor mij. Ik moest met de volgende zaken rekening houden:
  • De Angular app doet zijn requests met de withCredentials optie. Authenticeren gaat gewoon door een POST te doen op een /api/auth/authenticate met credentials.
  • Nadat ik de credentials heb gecontroleerd, laat ik het .NET Core framework een cookie maken door HttpContext.SignInAsync aan te roepen ( https://docs.microsoft.co...ookie?view=aspnetcore-3.0 ).
  • In mijn Angular router module gebruik ik een guard die een GET request doet op /api/auth/check. Krijg ik een 401 terug, dan navigeer ik naar het LoginComponent:
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuardService implements CanActivate {
    
      constructor(private backend: BackendService, private router: Router) { }
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
        return this.backend.authCheck().pipe(
          map(result => { 
            if (result) return true;
            this.router.navigate(['/login']);
          })
        );
      }
    }

    En de code in de BackendService:
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    
      authCheck(): Observable<boolean> {
        let url = `${this.backendUrl}/api/auth/check`;
    
        return this.http.get(url, { withCredentials: true }).pipe(
          map(data => true),
          catchError(err => of(false))
        );
      }

    Hier zou ik nog wat meer error handling kunnen doen, dat ik echt naar een 401 kijk, zodat de sessie niet verbroken wordt door andere communicatiefouten.
  • Ik moest .NET Core wel even vertellen dat hij een 401 moet geven en niet moet proberen naar een eigen login pagina te redirecten.
    code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
          services
            .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
              options.Events.OnRedirectToLogin = (context) =>
              {
                context.Response.StatusCode = 401;
                return Task.CompletedTask;
              };
            });
  • Uiteraard gaat alles via HTTPS.
  • Ik moest de Cookie policy nog aanpassen, zodat de cookie HttpOnly, SameSite en ook Secure zijn:
    code:
    1
    2
    3
    4
    5
    6
    7
    
          var cookiePolicyOptions = new CookiePolicyOptions
          {
            MinimumSameSitePolicy = SameSiteMode.Strict,
            HttpOnly = HttpOnlyPolicy.Always,
            Secure = CookieSecurePolicy.SameAsRequest // Voor development
          };
          app.UseCookiePolicy(cookiePolicyOptions);
  • ASP.NET Core versleutelt automatisch de cookie voor mij (ASP.NET Core Data Protection). Mocht ik in de toekomst ooit moeten load balancen, dan is het mogelijk om meerdere instanties dezelfde key ring te laten gebruiken, zodat alles blijft werken (al ga ik er niet vanuit dat dit ooit nodig is voor dit project).
Overwegingen om voor cookie auth te kiezen:
  • Schaalbaarheid is geen issue voor dit project. Het vervangt een oude management console die al 10 jaar lang op 1 server gehost werd. Het project wordt nieuw leven ingeblazen, maar zal naar alle waarschijnlijkheid zelfs minder users hebben dan de oude console ooit had (50 tot 100 geprojecteerd).
  • Het is veel simpeler in te bouwen dan een JWT based auth met IdentityServer etc.
  • Het is mogelijk een sessie te killen.
Mochten jullie nog op- en aanmerkingen hebben, graag :)
Cookie != Session :)

Hier staat nog wat meer op de MS site, mocht je ook Authorization willen toevoegen: https://docs.microsoft.co...ookie?view=aspnetcore-3.0. Die link had je al gevonden

Ook moet je wel de Session aan hebben staan en het Cookie laten verlopen anders heb je het zelfde als met JWT

Verder opletten dat je geen redirect doet na het uitloggen omdat dat anders niet werkt en denk wel aan CSRF

Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
GrooV schreef op dinsdag 1 oktober 2019 @ 08:10:
[...]
Cookie != Session :)

Ook moet je wel de Session aan hebben staan en het Cookie laten verlopen anders heb je het zelfde als met JWT

Verder opletten dat je geen redirect doet na het uitloggen omdat dat anders niet werkt en denk wel aan CSRF
Ik neem aan dat je bedoelt dat ik de SessionMiddleware moet gebruiken en dat dit iets anders is dan een cookie? (dat 1 van de mogelijkheden is om als session identifier te gebruiken)
code:
1
2
3
4
5
6
7
8
      services.AddSession(options =>
      {
        options.IdleTimeout = TimeSpan.FromMinutes(10);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
      });

      app.UseSession();

Voor de rest gebruik ik de volgende AuthenticationProperties bij het aanmelden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
          var claimsIdentity = new ClaimsIdentity(logon.GetClaims(), CookieAuthenticationDefaults.AuthenticationScheme);
          var authProperties = new AuthenticationProperties
          {
            AllowRefresh = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
            RedirectUri = null
          };

          HttpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity),
            authProperties);
        }

Het idee is dat authentication tickets na 10 minuten verlopen, maar omdat AllowRefresh aan staat, zou je een nieuwe moeten krijgen als je binnen die 10 minuten actief op de applicatie bent.

Wat CSRF betreft, zet ik de cookies met SameSite (Strict) en HttpOnly en ook Secure.

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
Lethalis schreef op dinsdag 1 oktober 2019 @ 09:11:
[...]

Ik neem aan dat je bedoelt dat ik de SessionMiddleware moet gebruiken en dat dit iets anders is dan een cookie? (dat 1 van de mogelijkheden is om als session identifier te gebruiken)
code:
1
2
3
4
5
6
7
8
      services.AddSession(options =>
      {
        options.IdleTimeout = TimeSpan.FromMinutes(10);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
      });

      app.UseSession();

Voor de rest gebruik ik de volgende AuthenticationProperties bij het aanmelden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
          var claimsIdentity = new ClaimsIdentity(logon.GetClaims(), CookieAuthenticationDefaults.AuthenticationScheme);
          var authProperties = new AuthenticationProperties
          {
            AllowRefresh = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
            RedirectUri = null
          };

          HttpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity),
            authProperties);
        }

Het idee is dat authentication tickets na 10 minuten verlopen, maar omdat AllowRefresh aan staat, zou je een nieuwe moeten krijgen als je binnen die 10 minuten actief op de applicatie bent.

Wat CSRF betreft, zet ik de cookies met SameSite (Strict) en HttpOnly en ook Secure.
Netjes gemaakt! Ik blijf zelf gewoon JWT gebruiken (omdat ik lui ben en het er nu toch al best goed werkend in zit 8) ), maar dit is inderdaad best een nette oplossing.

Over het horizontale scalen, krijg je met zo'n cookie oplossing niet alsnog het probleem dat de sessie er op de ene server wel is en op de andere niet. Dus dat je dan met loadbalancing bij een uitlog de sessie van alle servers moet gaan laten verwijderen?

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Jantje2000 schreef op dinsdag 1 oktober 2019 @ 09:17:
[...]
Over het horizontale scalen, krijg je met zo'n cookie oplossing niet alsnog het probleem dat de sessie er op de ene server wel is en op de andere niet. Dus dat je dan met loadbalancing bij een uitlog de sessie van alle servers moet gaan laten verwijderen?
Yes. Ik heb hier dan ook voor gekozen, omdat ik niet verwacht dat ik horizontaal hoef te schalen.

Hoe dit met .NET Core moet, heb ik eerlijk gezegd geen ervaring mee... maar vroeger met WebForms e.d. had je hier meerdere mogelijkheden voor. Je kon een losse SessionState service draaien, je kon de state ook in SQL Server opslaan (wat takke traag was), enzovoorts.

Dus hier zullen voor .NET Core ook oplossingen bestaan.

Maar eerlijk gezegd, zou ik dan wel JSON Web Tokens inbouwen.

Alleen het idee is dat wanneer de applicatie toch weinig gebruikers heeft, het totaal niet boeit en je net zo goed voor een simpele oplossing kunt kiezen.

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
Lethalis schreef op dinsdag 1 oktober 2019 @ 09:22:
[...]

Yes. Ik heb hier dan ook voor gekozen, omdat ik niet verwacht dat ik horizontaal hoef te schalen.

Hoe dit met .NET Core moet, heb ik eerlijk gezegd geen ervaring mee... maar vroeger had je hier meerdere mogelijkheden voor. Je kon een losse SessionState service draaien, je kon de state ook in SQL Server opslaan (wat takke traag was), enzovoorts.

Dus hier zullen voor .NET Core ook oplossingen bestaan.

Maar eerlijk gezegd, zou ik dan wel JSON Web Tokens inbouwen.

Alleen het idee is dat wanneer de applicatie toch weinig gebruikers heeft, het totaal niet boeit en je net zo goed voor een simpele oplossing kunt kiezen.
Ja precies.

De applicatie waar ik nu aan bezig ben moet gaan worden gebruikt door klanten van dit bedrijf. Ik weet natuurlijk niet hoe groot het gaat worden, maar ik kan met goed voorstellen dat er horizontaal gescaled zou moeten gaan worden. (Hoewel we op Azure draaien, dus ik zal daar dan weer niet extreem veel aandacht aan hoeven te besteden.)

Daarom had ik in eerste instantie ook gekozen voor JWT (ook omdat mijn docenten geleerd hadden dat dat een best practice is voor API's

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Jantje2000 schreef op dinsdag 1 oktober 2019 @ 09:17:
Over het horizontale scalen, krijg je met zo'n cookie oplossing niet alsnog het probleem dat de sessie er op de ene server wel is en op de andere niet. Dus dat je dan met loadbalancing bij een uitlog de sessie van alle servers moet gaan laten verwijderen?
De laatste keer dat ik met .Net werkte, in 2005 ofzo, kon je vrij simpel sessie state sharen tussen instances via MS SQL. Dat was toen al practisch plug and play. Natuurlijk heb je dan je sessie store als een bottleneck, maar het gaat lang duren voordat MS SQL (of een andere database) het te druk gaat krijgen met dergelijke simpele key-lookups.

Sowieso zou ik er altijd vanuit gaan dat je minimaal 2 instances van je service hebt draaien gewoon puur voor de fail-over. Stateful services, die dus zelf zaken in memory houden (behalve caches), zijn over 't algemeen een slecht idee. Het is simpel om direct goed te doen maar lastig naderhand te moeten fixen.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
Hydra schreef op dinsdag 1 oktober 2019 @ 09:55:
[...]


De laatste keer dat ik met .Net werkte, in 2005 ofzo, kon je vrij simpel sessie state sharen tussen instances via MS SQL. Dat was toen al practisch plug and play. Natuurlijk heb je dan je sessie store als een bottleneck, maar het gaat lang duren voordat MS SQL (of een andere database) het te druk gaat krijgen met dergelijke simpele key-lookups.

Sowieso zou ik er altijd vanuit gaan dat je minimaal 2 instances van je service hebt draaien gewoon puur voor de fail-over. Stateful services, die dus zelf zaken in memory houden (behalve caches), zijn over 't algemeen een slecht idee. Het is simpel om direct goed te doen maar lastig naderhand te moeten fixen.
Ja, en dit is natuurlijk geen .Net ding. Uiteindelijk is het gewoon een concept dat je gebruikt, of het nou in C# of in Java is, in beide gevallen wil je sessions over de servers kunnen delen.

Hoewel het natuurlijk mogelijk is dat Spring weer een eigen session management iets heeft, waardoor het gemakkelijker is dan door middel van database lookups.

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • +1 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Jantje2000 schreef op dinsdag 1 oktober 2019 @ 09:57:
[...]

Ja, en dit is natuurlijk geen .Net ding. Uiteindelijk is het gewoon een concept dat je gebruikt, of het nou in C# of in Java is, in beide gevallen wil je sessions over de servers kunnen delen.

Hoewel het natuurlijk mogelijk is dat Spring weer een eigen session management iets heeft, waardoor het gemakkelijker is dan door middel van database lookups.
Voor .NET Core kun je trouwens "Distributed Caching" gebruiken:

https://docs.microsoft.co...buted?view=aspnetcore-3.0

Dit slaat de state in SQL Server op, maar je kunt ook REDIS gebruiken. Met Spring kun je dit ook doen en heb je uiteindelijk dus hetzelfde effect:

https://medium.com/@gvnix...ession-redis-bdc6f7438cc3

PS
Dus als ik de door mij gekozen oplossing beter wil verwoorden:
- Ik heb een monolithische applicatie die het session management van het framework gebruikt.
- Om SPA's te ondersteunen gebruik ik cookies met een session identifier er in en heb ik het framework ook verteld dat cookies essentieel zijn.
- Mocht ik ooit horizontaal moeten schalen, dan kan ik de session state delen met meerdere instanties door een in memory cache zoals REDIS te gebruiken, of kan ik de state zelfs persistent maken door hem in SQL Server op te slaan.

Dat laatste kan trouwens handig zijn als je nog (zoals ik) in het stenen tijdperk leeft en zelf on premises servers draait. Bij een onverwachte reboot van een machine blijven de sessies van de gebruikers dus heel (als je niet te lang uit de lucht bent).

Bij een in memory cache moeten ze allemaal opnieuw inloggen. Aan de andere kant geeft een in memory cache betere performance.

Dus het is - zoals altijd - een afweging.

[ Voor 36% gewijzigd door Lethalis op 01-10-2019 10:31 ]

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
@Hydra @Jantje2000
Er is een probleem met de gekozen oplossing... althans daar lijkt het erg op momenteel. Op het moment dat de API op een ander domein staat dan de SPA, dan wordt de cookie gezien als een third party cookie en zullen veel moderne browsers weigeren de cookie op te slaan (in een poging privacy schendende tracking cookies tegen te gaan).

En dan werkt het dus simpelweg niet meer.

Tegen de JWT stroming inzwemmen heeft dus ook zo zijn nadelen als je met SPA's werkt en gewend bent een scheiding tussen SPA en API aan te brengen (ook qua deployment).

Plaats ik de API in hetzelfde domein, dan werkt het weer. Dus ik weet helaas vrij zeker dat het hieraan ligt.

Nu kan ik met een reverse proxy er wel voor zorgen dat de API altijd van hetzelfde domein lijkt te komen, maar dat maakt het qua deployment wel weer complexer.

Als jij Pietje bent en je hebt 10 users, dan kunnen die bij ons vaak inloggen op een eigen (sub)domein om het makkelijker voor ze te maken de URL te onthouden.

Wat zijn jullie gedachten hierover? :)

PS
Een andere oplossing zou zijn het inlogscherm volledig server side te doen met MVC. Dan navigeer je echt naar de URL toe. Maar ik vind dat eigenlijk niet zo mooi...

@Hydra
Hoe deploy jij SPA's die met sessions van een server side framework werken? Laat je de SPA dan ook hosten door de server side applicatie? (in het geval van .NET Core zou dat betekenen dat ik de SPA in de wwwroot map plaats bijvoorbeeld)

[ Voor 32% gewijzigd door Lethalis op 02-10-2019 16:39 ]

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
Lethalis schreef op woensdag 2 oktober 2019 @ 16:10:
@Hydra @Jantje2000
Er is een probleem met de gekozen oplossing... althans daar lijkt het erg op momenteel. Op het moment dat de API op een ander domein staat dan de SPA, dan wordt de cookie gezien als een third party cookie en zullen veel moderne browsers weigeren de cookie op te slaan (in een poging privacy schendende tracking cookies tegen te gaan).

En dan werkt het dus simpelweg niet meer.

Tegen de JWT stroming inzwemmen heeft dus ook zo zijn nadelen als je met SPA's werkt en gewend bent een scheiding tussen SPA en API aan te brengen (ook qua deployment).

Plaats ik de API in hetzelfde domein, dan werkt het weer. Dus ik weet helaas vrij zeker dat het hieraan ligt.

Nu kan ik met een reverse proxy er wel voor zorgen dat de API altijd van hetzelfde domein lijkt te komen, maar dat maakt het qua deployment wel weer complexer.

Als jij Pietje bent en je hebt 10 users, dan kunnen die bij ons vaak inloggen op een eigen (sub)domein om het makkelijker voor ze te maken de URL te onthouden.

Wat zijn jullie gedachten hierover? :)

PS
Een andere oplossing zou zijn het inlogscherm volledig server side te doen met MVC. Dan navigeer je echt naar de URL toe. Maar ik vind dat eigenlijk niet zo mooi...
Wil je de applicatie per se op een ander domein draaien? Misschien niet het alleernetsts, maar in .NET Core gebruik je in de start file
code:
1
services.addMvc()
. In plaats daarvan maak je dan gebruik van
code:
1
services.addSpa()
(of zoiets, maar hier lijkt het wel op), waarna dat probleem zou moeten zijn opgelost.

Dan krijg je in je project in plaats van een views folder een clientapp folder, waarin de Angular app komt te staan. Deze runt dan dus echt op hetzelfde domein.

Dan heb je echter geen compleet gescheiden front en backend meer, dus misschien verlies je dan voordelen die de redenen waren dat jij in dit project voor SPA hebt gekozen?

[ Voor 4% gewijzigd door Jantje2000 op 02-10-2019 16:38 ]

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Jantje2000 schreef op woensdag 2 oktober 2019 @ 16:37:
[...]
Wil je de applicatie per se op een ander domein draaien?

Dan krijg je in je project in plaats van een views folder een clientapp folder, waarin de Angular app komt te staan. Deze runt dan dus echt op hetzelfde domein.

Dan heb je echter geen compleet gescheiden front en backend meer, dus misschien verlies je dan voordelen die de redenen waren dat jij in dit project voor SPA hebt gekozen?
Dit hoeft niet per se een probleem te zijn, maar ik ben wel benieuwd hoe hier tegenaan wordt gekeken.

Op zich kan ik zelfs het hele frontend / SPA ontwikkelen in de wwwroot van mijn .NET Core applicatie en het als 1 geheel deployen. Microsoft heeft de wwwroot ook om die reden in het leven geroepen.

De reden om voor een SPA te gaan, is voornamelijk interactiviteit. Omdat de projecten een vrij hoge mate van dynamische content hebben, is het bouwen ervan met MVC een soort schizofrene oplossing, omdat je uiteindelijk toch een soort tweede applicatie in JavaScript ernaast aan het bouwen bent voor alle dynamische content.

Als het dan toch al die kant op gaat, kun je net zo goed een aparte SPA hebben en krijg je meteen ook een natuurlijkere development flow erbij (betere scheiding client vs server side code).

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • robbens
  • Registratie: Oktober 2019
  • Laatst online: 20-01 11:28
Zoals @Jantje2000 het voorlegt gaan we ervan uit dat je in één project werkt. Angular, react, vue.js en andere frameworks hebben ondersteuning voor observables (Javascript / Typescript: https://angular.io/guide/observables). Door dit te introduceren kun je een échte afscheiding maken tussen front- en back-end. Als je je back-end via REST draait, kun je gebruik maken van technologieën zoals async gecombineerd met observables.

Dit zorgt ervoor dat je meerdere pagina's kan transformeren in een SPA (je gebruikt bv. de angular routing module) - en je data in een back-end logisch afgesplitst heb. Dan ben je ook alvast begonnen aan een stukje SOLID: wie wordt daar niet blij van?

Edit: als je complexe data hebt die ook nog is dynamisch is kan ik MVC niet aanraden. Dan is de bovenstaande aanpak logischer (en vaak ook een heel stuk meer solide omdat je geen spaghetti-code hebt).

[ Voor 12% gewijzigd door robbens op 02-10-2019 16:48 ]


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
@robbens De discussie MVC vs SPA is eigenlijk al voorbij als je dit topic helemaal doorleest ;) Eigenlijk zou ik een nieuw topic aan moeten maken voor waar ik nu mee bezig ben: het managen van sessies in SPA's.

Waarbij de discussie vooral is: gebruik je gesignde tokens zoals JWT, of laat je de sessie managen door een server side framework dat bijvoorbeeld een versleutelde cookie genereert met een sessie id.

Op het moment dat je voor die laatste oplossing kiest, kun je dus ook met andere zaken te maken krijgen, zoals de herkomst van de cookie (het mag geen third party cookie zijn) of bepaalde aspecten bij horizontale schaalbaarheid (sessies bewaren in centrale store bijv).

Het oorspronkelijke argument om niet voor JWT te kiezen, is met name dat voor kleine projecten de voordelen van JWT nauwelijks opwegen tegen de nadelen ervan.

Anyways... ik ben een beetje een web dinosaurus die up to speed probeert te komen :P Meeste ervaring heb ik ooit met ASP.NET Web Forms opgedaan _O- Daarna jaren lang alleen maar Windows applicaties geprogrammeerd, dus vergeef me enige naïviteit op dit front.

Ik heb wel met Angular aan bestaande projecten gewerkt, alleen ik kom er gaandeweg wel achter dat mijn collega's ook niet altijd de meest weloverwogen beslissingen hebben genomen (zoals JWT tokens genereren die uren lang geldig blijven, omdat het refreshen ervan "lastig" is).

Uiteraard ben ik weer degene die tot op de bodem alles wil uitzoeken en begrijpen, zodat ik geen shit aflever. Maar ook omdat ik mezelf geen slechte gewoontes wil aanleren.

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • robbens
  • Registratie: Oktober 2019
  • Laatst online: 20-01 11:28
@Lethalis Ah, sorry, da's mijn fout.

JWT's zijn handig (let op dat je ze goed opzet!). Het is ietsjes lastiger in het begin, maar als je het doorhebt is het een hele fijne methodiek om mee te werken.

Hier geldt de aloude discussie voor:
Wat wil je bereiken, en wat wil je beveiligen?
Heb je zwaarwegende persoonlijke gegevens dan zou ik een combinatie aanpak doen. Gebruik je de login alleen om wat zelf-verzamelde gegevens van de gebruiker te laten zien dan zou ik het simpeler oplossen. De beste manier om een goede, doordachte keuze te maken is om een kosten-batenanalyse uit te voeren op jouw project.

Acties:
  • 0 Henk 'm!

  • Jantje2000
  • Registratie: Februari 2016
  • Laatst online: 22-09 20:32
@Lethalis https://docs.microsoft.co...re-3.0&tabs=visual-studio dat bedoelde ik.

Maar door dit te gebruiken doet het dotnet run commando ook gelijk een ng serve op hetzelfde domein. Dus dat is iets gemakkelijker dan de wist folder in de wwwroot te plaatsen

De wet van Murphy: Alles wat fout kan gaan zal fout gaan.


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Lethalis schreef op woensdag 2 oktober 2019 @ 16:10:
@Hydra @Jantje2000
Er is een probleem met de gekozen oplossing... althans daar lijkt het erg op momenteel. Op het moment dat de API op een ander domein staat dan de SPA, dan wordt de cookie gezien als een third party cookie en zullen veel moderne browsers weigeren de cookie op te slaan (in een poging privacy schendende tracking cookies tegen te gaan).
Ik snap niet wat dat met JWTs te maken heeft. Een JWT wordt meestal via een Auth header meegestuurd (Authorization: Bearer <Token>). An sich kan het met een cookie maar is niet standaard.

Hetzelfde geldt voor sessions; dit wordt vaak via cookies gedaan maar hoeft natuurlijk absoluut niet. Je kunt in de meeste frameworks zelf inregelen waar die session ID vandaan moet komen. Dit kan ook (wederom) gewoon een token in een header zijn.
@Hydra
Hoe deploy jij SPA's die met sessions van een server side framework werken? Laat je de SPA dan ook hosten door de server side applicatie? (in het geval van .NET Core zou dat betekenen dat ik de SPA in de wwwroot map plaats bijvoorbeeld)
Ik server over het algemeen meestal zowel de SPA als de API via een reverse proxy (Traefik bijvoorbeeld). Dan is wat daar 'achter' zit niet meer relevant, dat komt volgens de browser allemaal van hetzelfde domain.

Ik gebruik over 't algemeen geen sessions trouwens maar gewoon een login met een secret bearer token.

https://niels.nu


Acties:
  • +1 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Ik heb voor de discussie over sessies een apart topic aangemaakt:

Session management en Single Page Applications

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • GrooV
  • Registratie: September 2004
  • Laatst online: 10:00
Overigens met een SPA kan je wel heel goedkoop alles in Azure hosten, Static website in Azure Storage, API in Azure Functions, "DB" in Azure Table Storage.

Kost geen drol en je kan maximaal schalen, kan natuurlijk ook een afweging zijn :)

Acties:
  • 0 Henk 'm!

  • Antrax
  • Registratie: April 2012
  • Laatst online: 13:13
Hydra schreef op maandag 30 september 2019 @ 09:00:
Omdat je, sorry, de verkeerde tool voor de job gebruikt. Gebruik voor persistence van logins gewoon login-cookies. JWTs zijn vooral bedoeld in grote gedistribueerde systemen waar je niet wil dat voor iedere API call een login server geraakt wordt, die wordt dan eens in de 10 minuten ofzo geraakt (voor de refresh en de initiele logins). Als je JWTs in cookies op gaat slaan, en/of die dingen langer geldig laat zijn dan 10 minuten ofzo, dan sla je aardig de plank mis.
Dan sla ik de plank mis met de verkeerde gereedschap.

Ik vind mijn oplossing _redelijkerwijs_ genoeg voor de applicatie die ik bouw. Bovendien staat half internet, inclusief sommige grote gewaardeerde websites, vol met dezelfde voorbeelden (zelfs als je de zoekfilter instelt op 2019). Het enige is dat ik uit eigen initiatief zelf extra controle checks heb ingebouwd zowel als bij React als in mijn PHP backend.

Ik vind jouw reactie dat ik de verkeerde tool voor de job gebruikt dan ook een beetje raar maar ik snap je wel. Niet iedere developer werkt hetzelfde :)

.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!

Pagina: 1 2 3 Laatste