aspnet-contrib / AspNet.Security.OpenIdConnect.Server

OpenID Connect/OAuth2 server framework for OWIN/Katana and ASP.NET Core
560 stars 149 forks source link

Invoke token generator manually from controller #194

Closed pjeannet closed 8 years ago

pjeannet commented 8 years ago

Hi, I'm using ASOS to secure my mobile API where I need to integrate both local and external account. The app send the external token to the api after a clientside athentication and I need to generate local access tokens after checking this external token. I would like to know if it is possible to invoke the token generator from the controller to send back the local token to the mobile app.

Thanks.

stephenstroud commented 8 years ago

You can't invoke the token generator but could do a http call to it when you receive the call back.

You can extend the OpenIdConnectServerProvider public sealed class AuthorizationProvider : OpenIdConnectServerProvider

and exchange your external token within this method. you need to use 'destination' within your claim types.

public override Task GrantCustomExtension(GrantCustomExtensionContext context) { return base.GrantCustomExtension(context); }

kevinchalet commented 8 years ago

Salut :smile:

As mentioned by @stephenstroud, invoking the token generator in your own code is not something you can (or should) do, as creating tokens is heavily dependent on the OAuth2/OIDC context (the client application that requested the token, the resource server that will use it...).

Concerning the "token exchange" process you're describing, you have to be EXTREMELY careful when implementing it, as it's the best way to open a huge security hole in your authorization server: you MUST absolutely ensure that the client the external token was issued to a fully trusted application (i.e an application you own), or it will allow every third-party developer to use their own external tokens to get an ASOS access token, and thus access your API without user's consent.

If you really want to implement a custom "token exchange" flow, you can use the GrantCustomExtension event, as suggested by @stephenstroud.

pjeannet commented 8 years ago

Thanks for the answers. TBH I'm new to mobile apps and securing the backend api so I'm kind of struggling with this but I'm slowly seing the big picture. I only want facebook auth in addition to the local accounts so I did implement an external token checking with their graph API. It needs a secret appToken with the userToken so I think it will be sufficient to avoid other apps than mine to consume the API. But if you have a better way to implement the whole thing I'm open to any suggestions : I'm partly using your sample projects as well as other tutos ATM.

kevinchalet commented 8 years ago

It needs a secret appToken with the userToken so I think it will be sufficient to avoid other apps than mine to consume the API.

If you're using the "debug token" endpoint, then yes, it should prevent this kind of attack and return an error if the received token was not issued to the client application represented by the application token.

But if you have a better way to implement the whole thing I'm open to any suggestions : I'm partly using your sample projects as well as other tutos ATM.

The recommended approach is the one we use in OpenIddict and in the MVC sample: handling the external authentication flow directly in the identity server. It offers the best compromise between security and UX.

We have plans to implement the OAuth2 token exchange drafts in ASOS, but FB won't likely support them, so rolling your own grant type (via GrantCustomExtension) will still be your best chance if you don't want to use the "classic" approach.

pjeannet commented 8 years ago

Sorry I did not see your answer before my holidays and just came back today.

The recommended approach is the one we use in OpenIddict and in the MVC sample: handling the external authentication flow directly in the identity server. It offers the best compromise between security and UX.

Correct me if I'm wrong but this approach would use cookies for external providers and I'm not sure it would work for a mobile app?

kevinchalet commented 8 years ago

Correct me if I'm wrong but this approach would use cookies for external providers and I'm not sure it would work for a mobile app?

You basically have 2 options when opting for this approach:

In both cases, using cookies shouldn't be a problem :smile:

pjeannet commented 8 years ago

In both cases, using cookies shouldn't be a problem :smile:

Nice! I can go with the recommended approach then, and it seems easier.

Thank you :smile:

kevinchalet commented 8 years ago

You're welcome. Don't hesitate to ping us if you still need help! :smile:

pjeannet commented 8 years ago

Ok, I did some changes using oppenidict as an example : the server is handling the login form part and then calls the provider. I manage to sign in a user using Facebook with a web browser but now I am a bit lost about how I should get a token from the app.

I looked at the code and both flows in your sample : calling the login from the client or the server. When the call comes from the client, oppenidict change the returnurl to a confirmation page and then sends the token back with a return to the client app.

I tried to reproduce what you did, taking the code from your Accept() function and end up with an always null var request = HttpContext.GetOpenIdConnectRequest(); I suppose I need to call a special endpoint of the OpenIdConnect.Server that will then give access to the login page and create the OpenIdConnectRequest but I don't see how you did this in your sample.

Sry for being such a bother u_u

kevinchalet commented 8 years ago

Have you implemented your own MatchEndpoint notification? https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/vNext/samples/Mvc/Mvc.Server/Providers/AuthorizationProvider.cs#L95

pjeannet commented 8 years ago

Nop, I didn't know it existed ^^' So I just need to provide one and redirect to this endpoint after successful login?

kevinchalet commented 8 years ago

Yep.

pjeannet commented 8 years ago

I finally made it! The answer was to start back from scratch using your mvc server sample and calling it with a blank cordova app. Now I can start to work on the frontend. The only thing that I would like to change is to remove the "confirm access" view after registration as I don't see a case where a user would refuse (only apps that we own will access the protected APIs), but I'll let it like this for the moment.

Thank you a lot for all the help, tell me if you need the cordova sample.

kevinchalet commented 8 years ago

Great! :clap:

Thank you a lot for all the help, tell me if you need the cordova sample.

Sure, that would be great if you could submit it to https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Samples :smile:

pjeannet commented 8 years ago

I did the app, wanted to post it yesterday but my vs android emulator did not want to debug anymore. However GitHub is refusing me to post to the sample repo, do you need to grant me some extra permission?

kevinchalet commented 8 years ago

However GitHub is refusing me to post to the sample repo, do you need to grant me some extra permission?

You need to fork the samples repository and push your changes to your fork. Then, you can submit a PR I can merge to incorporate your changes to the main repository :clap: