I have an OIDC server setup for authentication and authorization. And I also have a desktop application which is essentially a browser with some extra functions.
The application makes calls to a API server directly and the embedded browser visits a web application that also makes requests to the same API server. Everytime the application is executed, user is required to login once.
Should I use hybrid flow? Can the tokens be shared between the app and web app?
I would also like to know how does the Facebook mobile app do authentication with its native part and web view part.
Edit: the web application is a server side MVC application
If the web application is an SPA, and thus a public client, then you can simply use the implicit grant type and pass the access and ID tokens from the embedded browser to the native application.
But assuming the web application is a server side application and thus a confidential client, then you would most likely want to use the authorization_code flow as the basis, since it will give you access to a refresh_token if needed on the server and you can rely on the Authorization Provider's TLS certificate for trust.
You can now choose whether to render back the access token from the server to the frontend, or to use a hybrid flow as you say. The latter would allow you to already pass the ID Token and access token to the native application without waiting for the backend call to the token endpoint and the page refresh to complete.
However, when processing tokens client side you must verify the ID Token signature and match the access token to it via at_hash since you can't rely on the TLS certificate of the token endpoint in that case.
Related
I have a web app (C# / Javascript) where I want to call a back-end service that I own. I want to secure that service so only my app(s) can call it. Seems like if I use Oauth on the client side, the secret is exposed? All the docs I read about Oauth give solutions when the user of the app owns the resource, not when the app itself owns it. I was looking at how google apis work, and the JavaScript libraries seem to expose the key on the client side, no?
Yes you can accomplish this with OAuth, but how you go about it depends on the details of how the data accessed via your back-end service is organized. If the data is actually user-specific, then your user really is the resource owner. In this case you would use the typical authorization code grant. With this grant type you register a client with the OAuth auth server and receive a client_id and client_secret. The client_id is, indeed, exposed in the browser, but the client_secret sits in your web app server and is never exposed. It is only sent on back-channel (non-browser) requests to your auth server. The main thing here is that only your own client web app would be registered and receive the client_id/client_secret. You simply need to not provide any public registration endpoints so no other clients can register. With this grant type, in order for your web app to gain authorization to access the user's data on the back-end service, the user would need to approve the authorization in the browser as part of the process.
On the other hand if the data you're accessing on your back-end service is not user-specific, then you can use the OAuth Client Credentials grant. With this grant type you register the client as before and receive a client_id and client_secret. The secret is stored securely on your web app server and only passed in back-channel requests. You would avoid allowing any other clients to register. Your web app can then gain authorization to your back-end service without even needing any user authorization in the browser.
I'm afraid there is no way to restrict your API to be called just by the code of your applications. Browser applications with public codes cannot hold any secret (such as certificate), that would identify them, because anyone can extract it from the code. Desktop and mobile applications compiled to bytecode are not so easy to read, but with some effort, attacker could find the secret data. That's also the reason why these applications (so called public clients) don't hold client_secret if they act as OAuth2 clients. They use a one-time secret instead - PKCE.
What you can do, is to check the audience (what client ID the token was issued for) of an access token sent from a frontend application to your backend. You can get this info either from the token introspection endpoint (aud attribute) or from JWT attributes if the token is of JWT type.
We're in a scenario where a single page application that we develop ourselves (AngularJS front end with https server APIs in the back) opens another
web application developed by a partner of ours in a new browser tab, and where this second web application needs access to a https server API that is also developed by us.
After looking around for possible solutions, we have now created a proof of concept using IdentityServer4, where the second web application is configured as a client with "authorization_code" grant type. When all applications are running on the same domain, the third party application is able to access our https server API without being prompted for user id and password.
The implementation of the second web application in this proof of concept is very much like the solution presented by bayardw for the post
Identity Server 4 Authorization Code Flow example
My question now is:
When - in production - the second web application no longer shares domain with our application and our https server API, will a call from the second web application be prompted for username and password when accessing our http server API?
Seems, you are missing some major things. First of all any API should never ask for username and password. Instead your app(s) should put a token into each request and API should validate that token. Where the user credentials should be asked is when a user accesses your (or 3-rd party) web application. Then Identity Provider creates an Identity token (usually to be persisted in a cookie and used within the app) and access token (to be provided to APIs). Each token is issued for specific Client (app) pre-registered in IdP. Probably when been hosted at the same domain your two apps shared the identity cookie and Client Id what is not correct. In production scenario you have to register the apps separately. All the rest should work fine (if you follow the routine i briefly described at the beginning).
Chosing to post an answer myself from feedback through other channels:
This boils down to the session tracking of the IdP. If cookies are being used to track IdP session, the behavior is impacted by whether a session cookie or a persistent cookie is used.
In general, I have found that Robert Broeckelmann has great articles on medium.com.
We want to code a web-application (with ASP.NET Core) that starts a legacy Windows desktop application via a custom URL protocol. The web-application must use an authorization server for obtaining an access (bearer) token via OAuth 2 with which it has access to the user's resources via an ASP.NET Core Web API. The desktop application must be able to access the user's resources via the Web API too. How can the desktop application obtain an access token?
I can think of the following options:
The desktop application shows a login screen, sends the entered username and password to the authorization server (using the “Resource Owner Password Credentials” grant type of OAuth 2) and gets an access token back.
The desktop application shows an embedded browser window. The embedded browser requests the OAuth Authorize endpoint of the authorization server (using the “Authorization Code” grant type of OAuth 2) and the user must log-in to authorize. The authorization server redirects back to the redirect URL. The desktop application intercepts this redirect, extracts the authorization token and uses it to get an access token.
The web-application starts the desktop application and passes its access (bearer) token as an argument to the desktop application.
Before starting the desktop application, the web-application requests a new authorization code from the authorization server. The web-application starts the desktop application and passes the authorization code as an argument to the desktop application. The desktop application exchanges the authorization code for an access token by sending the authorization code to the OAuth Token endpoint of the authorization server.
We do not wish to use the first and second option, because we want single sign on.
The third option does not seem to be a good idea, because malicious software on the user’s desktop PC can obtain and use the access token too.
The fourth option seems to be the only option left. As far as I know an authorization code is a temporary (short-lived) one-time token. Besides that, you need to know the client secret for obtaining an access token.
Can anyone confirm that option four is the way to go? Or did I overlook something?
Are there any examples with IdentityServer for this scenario?
Both application should share a logon session using the system browser. This way the user gets SSO in the native app (and even vice versa).
The spec describes the best practices for native apps:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-12
In your case there is a flow that is made specially for desktop application:
Client Device Flow for OpenID connect allows Application that do not have any "browser capability",this Flow will typically suit well Desktop applications.
I'm immensly confused as to which OAUTH/OIDC flow to use when...
I've put together the following list to work through the options, and would appreciate someone correcting me if I'm getting it wrong. Thank you.
What I think I've understood so far is the following use cases:
A server-generated views web app (eg: ASP.NET or ASP.MVC based) that is refreshing on every request, and does not use AJAX to access authenticated APIs: use authorization code grant type flow.
A server-generated views web app (eg: ASP.MVC based) that is refreshing often, but does use AJAX to access authenticated APIs, and the server does not access 3rd parties APIs either as itself (the app) or on behalf of the user: use authorisation code grant type flow
server set session cookie to access APIs.
A server-generated views web app (eg: ASP.MVC based) that is refreshing often, but does use AJAX to access authenticated APIs, and the server does access 3rd parties APIs as itself (the app): use authorisation code grant type flow
server set session cookie to access APIs + use client credential grant type flow.
A client-side generated views web app (SPA), where the client invokes authenticated API endpoints on its source server, and the server does not invoke 3rd parties services as either itself (the app) or as the user: use implicit grant type flow, caching the authentication token in the user agent's sessionstorage, and passing the authentication_token* back on every request as a Bearer Token.
A client-side web app (SPA), where the client invokes authenticated API endpoints on its source server, and the server does invoke 3rd parties services as itself (the app): use implicit grant type flow, caching the authentication token in the user agent's sessionstorage, and passing the authentication_token back on every request as a Bearer Token, and use the client credential grant type flow*.
This probably is the most uncertain one: A client-side web app (SPA), where the client invokes authenticated API endpoints on its source server, and the server does invoke 3rd parties services as the the user: use implicit grant type flow, caching the authentication token in the user agent's sessionstorage, and passing the authentication_token back on every request as a Bearer Token, which the server can pass on to the 3rd party services (CHECK) to authenticate the user with. As the token is only encoded and signed, not encrypted, the token's claims can be read. Note: that may contain claims not intended for the 3rd party service.
Alternatively the flow might be:
The UI could precheck that the User is allowed to access the 3rd party service (eg: Order Flowers) and gray out the functionality to use the server api that will invoke the 3rd party service till the user has collected and stored a second authorisation token (but then how would the user agent pass that token back, if the call to the API was already using the authorisation header for its own bearer token?)
I am using thinktecture identity server v3. I created web application and web api service. when I am accessing the web application, I got the access token from identity server. I used this token as bearer token to communicate with web api. Everything works fine.
But I noticed that at api server, for every request with access token, it automatically calls the identity server. If the idenity server is up, then it served otherwise it gives unauthorize error.
What is the purpose of this call?
What data it carries with the call?
If it is for validating the authority, it will more burden to the identity server.
Is it possible to skip this call?
You cannot avoid this:
when a user authenticates with the identity server, it creates a token which is given to the client to indetify itself. This token is created on the fly by the identity server, which remembers it
the client presents this token to your Web API server, which knows nothign about it, but knows who can validate it. So your Web API server communicates with the identity server so that it can get the identity back from the identity server
That's the reason why it works this way.
If you wanted to avoid this behavior you could map the identity from the external identity server to an identity controlled by your own web API server, and use an authentication method under your control to avoid querying the token from the external identity server. However, if you're using an identity server is precisely becasue you don't want to implement it by yourself, so this option makes no sense. This option is used when you want to map users from popular external identiy servers (like Google or Facebook) to users under your control.