Recently we had a couple of customers that needed to connect their native desktop and mobile applications to an OpenID Connect and OAuth 2.0 back-end.
We always had samples that showed how to do this, but making them re-usable and cross-platform was a bit harder than I originally thought. At the same time the IETF released some good guidance around OAuth 2.0 for native applications (draft-spec) that I wanted to incorporate.
The end result of that is IdentityModel.OidcClient, which is a PCL that runs on desktop .NET, WinRT/UWP and Xamarin iOS and Android. It encapsulates all the protocol and crypto work needed for OpenID Connect Hybrid Flow with PKCE and can reduce all those steps to a few lines of code:
var client = new OidcClient(options); var result = await client.LoginAsync();
The result object will contain the claims of the user as well as an access token and refresh token (if requested).
The second problem I wanted to solve is keeping the access tokens fresh without putting too much logic into the client application. This is done by an HTTP message handler that you can plug into HttpClient. The handler will add the access token to outgoing requests and try to refresh the token whenever it sees a 401 response. You would then use this one HttpClient throughout your code:
_client = new HttpClient(result.Handler); _client.BaseAddress = new Uri("https://demo.identityserver.io/api/");
You can find more code snippets in the readme and the samples repo contains sample WinForms, UWP and iOS clients.
OSS FTW
To create such a library as a PCL was a combined effort – I’d like to thank Andrew Arnott for PCLCrypto and dvsekhvalnov for building Jose-Pcl on top. Without them JWT validation wouldn’t be possible.
I pushed a 1.0 to nuget – but there is still a lot of work. I opened a couple of issues already which are all up for grabs.
We also need more samples – Android, WPF and console hosts come to mind. Please support OidcClient and the above libraries by giving feedback and maybe contributing to them.
HTH
there is the possibility of using with Cordova Plugin?
Don’t think so – It is for native applications.
Don’t know anything about Cordova though.
Apache Cordova is an open-source mobile development framework. It allows you to use standard web technologies – HTML5, CSS3, and JavaScript for cross-platform development and a plugin is a package of injected code that allows the Cordova webview within which the app renders to communicate with the native platform on which it runs. Can I use this project for testing with my Cordova APP?
I know what Cordova is. And my answer is still “I don’t know”.
Automatic refresh of the token is very cool. Nice!
Love the HttpHandler for 401 responses.
The NuGet package has dependency on Microsoft.Bcl.Build which isn’t compatible when trying to add it to an Android (Native) Xamarin project. Any tips on how to add the library to my MonoAndroid V6 framework project?
The sample repo has an Android sample that seems to work.
I’m able to add the package to a PCL that will be referenced from my Droid project. When I was prototyping and trying to add directly to my droid project, the Nuget package wasn’t compatible. Thanks for the amazing work you guys are doing! The timing of this post was perfect for a project I’m currently working on.
Hi Dominic,
What would you suggest if we want to be able to use the SSO after the user closed the application (cookies in the User Agent are lost..) Is it a good aproach to store locally these cookies and set them in the IdentityServer domain when we re-open the WebView?
I hope I could explain my problem..
Thank you so much and keep up with the great work!
Cheers
No that’s not really good practice. Use the system browser (and maybe refresh tokens) instead
Yes that was my itentetion but if I use the system browser my standalone application cannot read the authorization response with all the tokens because the UA runs in a sandbox. For this I need to use an embedded browser like you do in your samples.. or am I am missing something here?
I’m already using refresh tokens but that does not allow me to open the webview and have the user immediately authentified (sso).
Thank you for your prompt reply.
Read the spec that I mention in my talk. This contains a lot of good guidance
sorry for missing something.
Thank you :)
Hi Dominick
I have been implementing Identity Server 3 for my company, replacing an existing STS server.
The goal was to better secure our existing API and allow us to move onto implementing a new API using WebApi 2.
We have a Windows offline client that is being worked on at the moment and this uses a WinForm for login. I have replaced the Login using the following from your colleague’s post here
I have identified a potential risk as we have 3 data centres that all have different domains but to new up an OIDC client we require the OIDC client options before we know anything about the user. See below.
The old STS captured a persons username via a dummy form and performed a try catch to return a secure token as a string. If that failed it would then use the username captured to go to the database and determine what data centre a user is attached to e.g US/UK/AUS and return the domain name as a string instead of a token.
My question is because the OIDC client requires the URI specified in the options before a user has even attempted to login, is there a recommended practice/approach for handling the potential of ID3 hosted on different data centres?
var authority = “https://localhost/stsv2/identity”;
var options = new OidcClientOptions(
authority,
“B461A498-6AD3-4489-8EFB-343979896019”,
“secret”,
“openid offline_access VFPToken”,
“http://localhost/native”,
new WinFormsWebView());
options.UseFormPost = true;
_oidcClient = new OidcClient(options);
Hi,
well – either you implement the fallback strategy inside your identityserver itself – or you need to try the different STSes one after another and check the response.
Please use SO for general IS quesions – or the github issue tracker for bugs/issues.
Am a bit confused with the existing IdentityModel library which already provides mechanise to communicate with OAuth 2.0 and OpenID Connect STS. Is this like a replacement or kind of extension that try to utilize “OAuth 2.0 for Native Apps” specs?
Appreciate your explanation Dominick.
yes – exactly. IdentityModel provides the low level protocol pieces – whereas OidcClient adds the UI related things.
I am new to the identity server. I downloaded OidcClient sample and it worked well with “https://demo.identityserver.io” but I cannot make it work with my local identityserver4. Do I have to create a native client with specific options in my local ID server 4?
Thank you
yes – you need to create a hybrid grant based client.
Why are you refreshing the access token if you see a 401 response? That won’t scale nicely for large sites, doesn’t it make sense to validate the expiry before using it and refresh if it is near or beyond the expiry? It saves a 401 roundtrip from mobile clients (which want to minimise connections) and reduces storms of 401s being recorded on the server – a problem which we had when an android app used that ‘refresh if it fails’ approach.
Genuinely interested.
The 401 status code is reserved for “credential invalid” – which translates to “the only thing I can do to solve this is to try a new token”.
This is one implementation strategy – not the only one.
Hi, whatever happened to this:
The second problem I wanted to solve is keeping the access tokens fresh without putting too much logic into the client application. This is done by an HTTP message handler that you can plug into HttpClient. The handler will add the access token to outgoing requests and try to refresh the token whenever it sees a 401 response.
I’m trying to implement this (now 4 years later) and cannot find this handler, is that still on the table?
IIRC – it’s this
https://github.com/IdentityModel/IdentityModel.OidcClient/blob/main/src/OidcClient/RefreshTokenDelegatingHandler.cs