C# Client App + Web API - gebruik van OpenID (Connect)

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 11-09 13:47

edeboeck

mie noow noooothing ...

Topicstarter
Goedenacht!

Ik loop al dagen vast over het volgende probleem:
  • Windows Forms app als client
  • ASP.Net Web API als server
Client wil boodschappen kunnen plaatsen op de server (call naar API plaatst boodschap in achterliggende SQL-Server) en boodschappen uitlezen. Voor het plaatsen moet geweten zijn wie de user is. Daarvoor wil ik OpenID Connect gebruiken. Wie authenticeert, maakt me op zich niet zoveel uit (of dit nu in de app via username+password is of via een externe login provider ala Google, Facebook, Twitter, Microsoft...).

Punt is vooral dat:
  1. de client de username mee moet doorgeven naar de API (net als het feit dat hij geauthenticeerd is)
  2. er bij voorkeur geen andere clients zijn die met de API kunnen communiceren... zo te zien heb ik daarvoor een access token nodig.
Sedert vorige week al zit ik in cirkeltjes te draaien en intussen zie ik door het bos de bomen niet meer terwijl het waarschijnlijk helemaal niet zo moeilijk hoeft te zijn. Ik ben o.a. op OpenIddict en IdentityServer4 uitgekomen, maar die zijn enkel voor ASP.Net Core (terwijl ik een "gewone" ASP.Net Web API op basis van .Net Framework 4.7 gebruik).

Zie ik het allemaal compleet fout? Zit ik in de goede richting? Is er wel een (eenvoudig) alternatief voor OpenIddict?

Benieuwd naar jullie reacties en input... alvast hartelijk bedankt! _/-\o_
edeboeck

Alle reacties


Acties:
  • +1 Henk 'm!

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 22:28

mulder

ik spuug op het trottoir

1) Jou applicatie zal de inlog moeten initiëren en krijgt dan een token terug. Deze geef je als Bearer mee aan de calls naar de API, in deze token zit de username in de claim
2) Hoe bedoel je dit, maar 1 klant tegelijk? Of dat alleen geauthoriseerde clients calls mogen doen?

Dat je de bomen door het bos niet meer ziet kan goed kloppen, er zijn veel verschillende terminologieën, versies, flows en libraries waar je goed gek van kan worden. Probeer goed het scenario dat je wilt bereiken te beschrijven en houd dat tegen de mogelijk oplossing aan (vooral welke Authorization Flow, welke OAuth versie en welke library)

Op GitHub zijn van de ADAL en de MSIL libraries van Microsoft een boel voorbeeld projecten te vinden, die potentieel voor jou geval geschikt zijn.

oogjes open, snaveltjes dicht


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 11-09 13:47

edeboeck

mie noow noooothing ...

Topicstarter
(voor iedereen die dit leest: mijn excuses voor de hele lap tekst... ik heb echter al een heleboel uitgeprobeerd en wil vooral de zaken correct krijgen... bedankt als je hiertoe bijdraagt! _/-\o_ _/-\o_ _/-\o_ )

Al heel erg bedankt voor jouw reactie @mulder ! Ik probeer even mee te gaan in de redenering.
mulder schreef op dinsdag 28 mei 2019 @ 15:10:
1) Jou applicatie zal de inlog moeten initiëren en krijgt dan een token terug. Deze geef je als Bearer mee aan de calls naar de API, in deze token zit de username in de claim
ok, dat is duidelijk (en komt overeen met een testproject waarmee ik gespeeld heb: het maakt gebruik van IdentityModel.OidcClient en een demo instantie van identityserver (https://demo.identityserver.io)... zoals ik het zie, moet ik zelf een eigen versie van die identityserver maken, klopt dat?
mulder schreef op dinsdag 28 mei 2019 @ 15:10:
2) Hoe bedoel je dit, maar 1 klant tegelijk? Of dat alleen geauthoriseerde clients calls mogen doen?
Dat laatste is inderdaad de bedoeling: enkel deze ene app (waarvan het uiteraard de bedoeling is dat er verschillende gebruikers zijn) zou gebruik mogen maken van de API.
mulder schreef op dinsdag 28 mei 2019 @ 15:10:
Dat je de bomen door het bos niet meer ziet kan goed kloppen, er zijn veel verschillende terminologieën, versies, flows en libraries waar je goed gek van kan worden. Probeer goed het scenario dat je wilt bereiken te beschrijven en houd dat tegen de mogelijk oplossing aan
Dit is het concept met de componenten:
  • een Windows Forms app die ik voor het gemak de client noem... de user gebruikt de client om berichten te lezen en te verzenden;
  • een ASP.Net (géén Core) Web API (voor het gemak API) die opgeroepen wordt vanuit de client;
  • een SQL-server instantie (DB) die zorgt voor de opslag van de berichten en de strikt noodzakelijke userdata.
Dus simpel geschetst krijgen we iets als:

( user <--> ) client <--> API <--> DB

Misschien niet onbelangrijk om te vermelden: in de DB staan alle messages versleuteld opgeslagen... het is pas op de client dat die ontsleuteld mogen worden. Omgekeerd wordt een message die de gebruiker opstelt al op de client versleuteld alvorens verzonden te worden.
Voor het bepalen van de juiste Authorization Flow, moet ik eerst al de terminologie correct kunnen toepassen... en daar heb ik wel wat twijfels bij... ik volg even de terminologie van deze pagina:
  • Resource Owner: omdat dit de entiteit is die toegang moet geven tot een afgeschermde resource, dacht ik aan de gebruiker
  • Application: deze vraagt toegang tot een protected resource in naam vd resource owner... hier dacht ik aan de API... of is het toch de client
  • Resource Server: er staat letterlijk " the server hosting the protected resources. This is the API you want to access."... de API dus
  • Authorization Server: deze moet de Resource Owner authenticeren en Access Tokens (de token waarvan je helemaal bovenaan spreekt) uitdelen na succesvolle aanmelding... de Authorization Server is dan een van de External Login Partners in dat geval? Maar kan de gebruiker zich dan nog met eenvoudige username+password aanmelden in de client?
  • User Agent: de agent die de resource owner gebruikt om te interageren met de application... in mijn situatie lijkt dat dus de client.
Mijn verontschuldigingen voor dit noob-gehalte, maar voor een nieuweling in het onderwerp is het inderdaad overweldigend.

Als bovenstaande veronderstellingen correct zijn, kom ik volgens het beslissingsschema voor OAuth 2.0 Grant uit op volgende redenering:
  1. Is the Application the Resource Owner? neen
  2. Is the Application a web app executing on the server?
    • Als het de API is, ja => Authorization Code Grant
    • Als het de client is, neen => ga verder
  3. Is the Application absolutely trusted with user credentials? als we hier komen, is Application == client => ja (in de veronderstelling dat de client de gebruikersgegevens veilig opslaat) => Resource Owner Password Credentials Grant
Het lijkt er dus op dat een correcte toepassing van de terminologie hierop al een antwoord geeft (dan is het natuurlijk nog een kwestie van dat geïmplementeerd te krijgen)... vraag is dus: welke toepassing van terminologie is de juiste?
OpenID (=> onderliggend OAuth 2.0) ... volgens hun eigen website is OpenID Connect de enige final specification, dus de te volgen versie.
Als ik bij de Certified OpenID Connect Implementations kijk, dan is er maar 1 C# library: IdentityModel.OidcClient 2.0 (hiervan komt ook het testproject waarover ik eerder sprak).
mulder schreef op dinsdag 28 mei 2019 @ 15:10:
Op GitHub zijn van de ADAL en de MSIL libraries van Microsoft een boel voorbeeld projecten te vinden, die potentieel voor jou geval geschikt zijn.
Hier is het een "ja maar"-probleem: als ik het goed begrepen heb, moet je voor ADAL altijd gebruik maken van Active Directory... dit is niet wat ik wil (b.v. een gebruiker zou ook met een FB- of Google-account mogen aanmelden).
Ik neem aan dat je MSAL i.p.v. MSIL bedoelt... daar lijkt het mij dat je ook sowieso Azure nodig hebt... als die aanname correct is, valt dat eigenlijk ook weer af (tenzij er anders echt geen goede oplossing voor mijn probleem is).
En er zijn inderdaad vele voorbeeldprojecten, maar tot nu toe heb ik er enkel gevonden die gebruik maken van Azure of (en vooral dit laatste) voor ASP.Net Core geschreven zijn... helaas heb ik daarvoor geen ondersteuning bij mijn hoster.

Beste Tweaker,
Als je tot hier geraakt bent met lezen, hartelijk dank... hier is een drankje voor de moeite :9B ... (ook wel een beetje in de hoop dat dat extra energie geeft om mij verder te helpen :+ oOo )

Thx!
edeboeck

Acties:
  • +1 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 00:32
IdentityServer (3 of 4) is een framework om een OpenID Provider te maken. De provider is de service die jou kan vertellen wie een gebruiker is. Die service is (vrijwel altijd) ook verantwoordelijk voor het bijhouden wie je gebruikers zijn. De gebruiker logt dus in op en via een pagina van de OpenID Provider. Dit is ook waarvoor OpenID Connect bedoeld is: vastleggen van een protocol om identity management as a service te kunnen krijgen.

IdentityServer4 is een framework bovenop .net core en daarmee alle samples ook. Gelukkig voor jou is er ook nog IS3 welke voor .net full framework is. Hier is bijv. een tutorial voor het beveiligen van een MVC applicatie: https://identityserver.gi...ew/mvcGettingStarted.html

Verder zijn er een groot aantal samples over hoe je een .net full framework applicaties kan beveiligen met OIDC te vinden in de IS3 repo: https://github.com/Identi...ients/MVC%20OWIN%20Client
Wat handig is om te weten is dat, gelukkig, de meeste van deze samples ook zullen werken met providers zoals IS4, auth0, keycloak, etc. Dat betekend dat je de provider kant niet per se zelf hoeft te implementeren, of iig niet vastzit aan een bepaalde specifieke implementatie, en kan focussen op de client en configuratie kant.

Qua flows lijkt mij overigens uit het verhaal dat de 'hybrid' flow de beste match is, onder de aanname dat de client graag zelf ook wil weten wie de gebruiker is.

Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 11-09 13:47

edeboeck

mie noow noooothing ...

Topicstarter
Hoi @Caelorum , bedankt voor je uitgebreide antwoord.
Die tutorial waar je naar verwijst, was ik al tegengekomen, maar had ik toen om een bepaalde reden toch links laten liggen (zoals gezegd: na een tijdje was ik nogal "murw" gemept). Nu ik het herlees, kan dit me toch wel op weg zetten... bovendien staat er ook een voorbeeld voor een external login provider (Google), dus dat lijkt al heel goed.

Bedankt voor die link naar IS3 Samples... ik had er hier al verscheidene gecloned... ik was er echter mee gestopt omdat het in veel gevallen compleet verschillend lijkt (waardoor je als noob helemaal de weg kwijt raakt).

Wat de flow betreft: het is inderdaad de bedoeling dat de client ook weet wie de gebruiker is... zo kan hij de juiste messages ophalen.
Als ik jouw link lees, dan lijkt het erop dat ik inderdaad hybrid flow nodig heb.

Alvast ook bedankt voor jouw input... ik ga ermee aan de slag (en zal hier nog update geven: hetzij in de vorm van 'SOLVED' of nog met enige issues... uiteraard hoop ik op het eerste ;) !

Acties:
  • +1 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
edeboeck schreef op dinsdag 28 mei 2019 @ 22:49:
Wat de flow betreft: het is inderdaad de bedoeling dat de client ook weet wie de gebruiker is... zo kan hij de juiste messages ophalen.
Als ik jouw link lees, dan lijkt het erop dat ik inderdaad hybrid flow nodig heb.
Om de juiste messages op te halen hoeft de client toch niet te weten wie er is ingelogd, dat hoeft de API alleen te weten, dan heb je gewoon een endpoint like : https://www.my-api.nl/v1/my/messages, en geeft de API alle messages voor de authenticated persoon terug.

Voor OpenID ( en andere federated authentication schemas ) is het belangrijk om goed te beseffen dat de authenticatie door een andere service afgehandeld wordt dat de daadwerkelijke resource die je probeert te benaderen. Je API hoeft dus eigenlijk niks te weten over authenticatie, behalve dat hij access_tokens gesigned door een bepaalde 3e partij support ( en kan interpreteren dus ;) )

De daadwerkelijke authenticatie wordt afgehandeld door een IdP die je inderdaad bijvoorbeeld met IdentityServer kunt implementeren. Als je nog meer federatie wil doen, naar bijvoorbeeld facebook/google/etc. dan zou ik dat ook binnen je eigen IdP regelen, dan hoef je voor je API maar 1 trusted party te hebben, en hoef je die ook niet aan te passen als je nog andere authenticatie methoden toe wil voegen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 11-09 13:47

edeboeck

mie noow noooothing ...

Topicstarter
Woy schreef op woensdag 29 mei 2019 @ 08:46:
[...]
Om de juiste messages op te halen hoeft de client toch niet te weten wie er is ingelogd, dat hoeft de API alleen te weten, dan heb je gewoon een endpoint like : https://www.my-api.nl/v1/my/messages, en geeft de API alle messages voor de authenticated persoon terug.
Bedankt voor je reactie Woy! Volgens mij is dat in mijn geval wel nodig: de messages moeten immers versleuteld worden. Om de communicatie op te zetten, gaat de server een symmetrische key versleuteld verzenden... deze versleuteling gebeurt met de publieke (asymmetrische) key van de user (deze bevindt zich in de DB op de server). Omdat de client deze moet kunnen ontsleutelen, moet die de private key van de user kennen... deze bevindt zich in een keystore op de client, maar daarvoor moet de user gekend zijn. Daarom ging ik ervan uit dat de client moet weten wie aangemeld is. Klopt deze redenering?
Woy schreef op woensdag 29 mei 2019 @ 08:46:
Voor OpenID ( en andere federated authentication schemas ) is het belangrijk om goed te beseffen dat de authenticatie door een andere service afgehandeld wordt dat de daadwerkelijke resource die je probeert te benaderen. Je API hoeft dus eigenlijk niks te weten over authenticatie, behalve dat hij access_tokens gesigned door een bepaalde 3e partij support ( en kan interpreteren dus ;) )

De daadwerkelijke authenticatie wordt afgehandeld door een IdP die je inderdaad bijvoorbeeld met IdentityServer kunt implementeren. Als je nog meer federatie wil doen, naar bijvoorbeeld facebook/google/etc. dan zou ik dat ook binnen je eigen IdP regelen, dan hoef je voor je API maar 1 trusted party te hebben, en hoef je die ook niet aan te passen als je nog andere authenticatie methoden toe wil voegen.
Ok, thnx voor dit inzicht! Ik probeer hiermee wat te brouwen.

Acties:
  • +1 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
edeboeck schreef op woensdag 29 mei 2019 @ 23:34:
[...]
Bedankt voor je reactie Woy! Volgens mij is dat in mijn geval wel nodig: de messages moeten immers versleuteld worden. Om de communicatie op te zetten, gaat de server een symmetrische key versleuteld verzenden... deze versleuteling gebeurt met de publieke (asymmetrische) key van de user (deze bevindt zich in de DB op de server).
Ik denk dat je nog een keer goed moet nadenken over wat je wil bereiken. Het klinkt nu alsof de server zowel de symmetrische key als de asymetrische public key heeft. Op dat moment is het eigenlijk gewoon transport security, en dat heb je ook al als je gewoon TLS gebruikt.

Het klinkt alsof je iets van end-to-end encryptie wil doen, maar dat houdt ook in dat de server niet de informatie behoort te hebben om te decrypten. Het encrypten van de decryptie sleutel moet dan op de versturende client kant gebeuren met een public key van de ontvanger. ( Of je moet een ander key-exchange algoritme kiezen, waarmee je van te voren de sleutels uitwisselt )

Maar bedenk je sowieso dat een goede encryptie schema best lastig is om goed op te zetten. Je moet al je randvoorwaarden duidelijk op een rijtje hebben.

[ Voor 4% gewijzigd door Woy op 30-05-2019 09:31 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • +1 Henk 'm!

  • PWSteal
  • Registratie: December 2013
  • Laatst online: 28-09 21:48
edeboeck schreef op woensdag 29 mei 2019 @ 23:34:
[...]
Bedankt voor je reactie Woy! Volgens mij is dat in mijn geval wel nodig: de messages moeten immers versleuteld worden. Om de communicatie op te zetten, gaat de server een symmetrische key versleuteld verzenden... deze versleuteling gebeurt met de publieke (asymmetrische) key van de user (deze bevindt zich in de DB op de server). Omdat de client deze moet kunnen ontsleutelen, moet die de private key van de user kennen... deze bevindt zich in een keystore op de client, maar daarvoor moet de user gekend zijn. Daarom ging ik ervan uit dat de client moet weten wie aangemeld is. Klopt deze redenering?


[...]
Ok, thnx voor dit inzicht! Ik probeer hiermee wat te brouwen.
Mag ik je vragen waarom het nodig is dat de messages versleuteld zijn? Tenzij het voor een studie project is, lijkt het me niet dat een boodschappenlijstje dermate privacy gevoelige informatie bevat om dit te doen.

Je hebt namelijk al 2 stappen in plaats om je verkeer af te schermen;
- API-Calls dienen via HTTPS te gaan, wat je dus al bescherming biedt tegen vele soorten aanvallen.
- Je client heeft geen informatie over de user ( + pass ), dit beheer je in IdentityServer in dit geval, en je API weet op basis van je token bij welke informatie je mag.

Acties:
  • 0 Henk 'm!

  • edeboeck
  • Registratie: Maart 2005
  • Laatst online: 11-09 13:47

edeboeck

mie noow noooothing ...

Topicstarter
Woy schreef op donderdag 30 mei 2019 @ 09:29:
[...]

Ik denk dat je nog een keer goed moet nadenken over wat je wil bereiken. Het klinkt nu alsof de server zowel de symmetrische key als de asymetrische public key heeft. Op dat moment is het eigenlijk gewoon transport security, en dat heb je ook al als je gewoon TLS gebruikt.

Het klinkt alsof je iets van end-to-end encryptie wil doen, maar dat houdt ook in dat de server niet de informatie behoort te hebben om te decrypten. Het encrypten van de decryptie sleutel moet dan op de versturende client kant gebeuren met een public key van de ontvanger. ( Of je moet een ander key-exchange algoritme kiezen, waarmee je van te voren de sleutels uitwisselt )

Maar bedenk je sowieso dat een goede encryptie schema best lastig is om goed op te zetten. Je moet al je randvoorwaarden duidelijk op een rijtje hebben.
Hoi Woy, bedankt om verder mee te denken. Ik heb me inderdaad niet goed uitgedrukt. Het is inderdaad de bedoeling om een end-to-end encrypted messaging systeem op te zetten. De symmetrische key bevindt zich inderdaad in de DB, maar in versleutelde vorm (versleuteld met de public key van de user).
Edwin__ schreef op donderdag 30 mei 2019 @ 11:23:
[...]Mag ik je vragen waarom het nodig is dat de messages versleuteld zijn? Tenzij het voor een studie project is, lijkt het me niet dat een boodschappenlijstje dermate privacy gevoelige informatie bevat om dit te doen.

Je hebt namelijk al 2 stappen in plaats om je verkeer af te schermen;
- API-Calls dienen via HTTPS te gaan, wat je dus al bescherming biedt tegen vele soorten aanvallen.
- Je client heeft geen informatie over de user ( + pass ), dit beheer je in IdentityServer in dit geval, en je API weet op basis van je token bij welke informatie je mag.
Hola hola, jij weet toch niet wat er op mijn boodschappenlijstje staat? Wel, net omdat dat versleuteld is. :+ ;) Alle gekheid op een stokje, het is inderdaad een onderdeeltje van een studieproject: het encryptieverhaal denken we redelijk goed te hebben, maar die OpenID is niet evident met onze gekozen set-up... en om nu alles te herschrijven naar en hosting te zoeken voor ASP.Net Core (heb daar geen ervaring mee, en ben wat huiverachtig om zo dicht bij de deadline de boel (weer eens) om te gooien).
Die OpenID is een bonus, geen verplichting, maar had ik er graag bij gehad.

Acties:
  • 0 Henk 'm!

  • GrooV
  • Registratie: September 2004
  • Laatst online: 04-10 15:27
Als je geen .net core wil gebruiken zou je nog (volledig op eigen risico en zal het niet adviseren) IdentityServer3 kunnen gebruiken: https://github.com/IdentityServer/IdentityServer3 let wel op, deze wordt niet meer ondersteund!

Verder hier nog een goede talk van de maker van Identity server over welke flows je nu zou moeten gebruiken YouTube: Building Clients for OpenID Connect/OAuth 2-based Systems - Dominick... en waar je clients op moeten letten

[ Voor 3% gewijzigd door GrooV op 03-06-2019 13:12 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:43
GrooV schreef op maandag 3 juni 2019 @ 13:07:
Als je geen .net core wil gebruiken zou je nog (volledig op eigen risico en zal het niet adviseren) IdentityServer3 kunnen gebruiken: https://github.com/IdentityServer/IdentityServer3 let wel op, deze wordt niet meer ondersteund!
De API die hij wil consumen is geen .NET Core. Echter, dat wil toch niet zeggen dat de service die de tokens uitgeeft (de authority) niet in .NET Core mag zijn ?

https://fgheysels.github.io/

Pagina: 1