I am creating this post after doing quite a lot of research on OpenID Connect myself including reading the specs and the more I read the more questions come up. I hope that someone is able to help me and clear my confusion.
The OpenID Connect specs are good but only contain very basic examples that do not match my usecase. Please let me try to explain my situation and then ask my question:
I try to use OIDC in conjuction with SharePoint Online and two applications. One is a webservice (back-end) that is supposed to interact with SharePoint and the other one is a simple single page application (front-end) running in the browser of the user that allows him to interact with the webservice. My IdentityProvider is Active Directory. The task of the webservice is to do some actions in user context on SharePoint but it is also supposed to allow the user to execute a limited set of actions that only an administrator of SharePoint would be allowed to do (e.g. I want to allow the user to create a SiteCollection but not delete it) For that reason I managed to register the webservice with SharePoint so that it receives a Special access_token which grants it admin access in SharePoint.
My thoughts so far:
1) If the user logs into SharePoint he receives an id_token and an access_token from the AD. He can use the id_token to log to SharePoint and interact with it directly. (I got this working)
2) I also want to authenticate the user in the front-end single page application because some users should not be able to make certain calls to the webservice and I want to hide these buttons from them in my application. For that I could use the id_token from step 1).
3) If my webservice should do something in the context of a user I can just pass the access_token that was created for that given user in step 1) to the webservice and then forward it to SharePoint.
4) If my webservice should execute a privileged function that the user is not allowed to do on his own, I want to use the Special access_token that the webservice already pocesses to make the call. In that case I have to authenticate the user at my webservice with his id_token from step 1) to make sure that I want to allow this request of his.
My question:
Does every client have to make a request for his own id/access_token? (These different flows are described in the OIDC and OAuth specs here and here) and will this still be Single-Sign-On?
Or can I just generate a single id_token and access_token for a user in step 1) and then pass these on to all clients that need them?
Thank you very much in advance!!
Related
My situation is this. I have a legacy Angular application which calls a Node API server. This Node server currently exposes a /login endpoint to which I pass a user/pwd from my Angular SPA. The Node server queries a local Active Directory instance (not ADFS) and if the user authenticates, it uses roles and privileges stored on the application database (not AD) to build a jwt containing this user's claims. The Angular application (there are actually 2) can then use the token contents to suppress menu options/views based on a user's permissions. On calling the API the right to use that endpoint is also evaluated against the passed in token.
We are now looking at moving our source of authentication to an oAuth2.0 provider such that customers can use their own ADFS or other identity provider. They will however need to retain control of authorization rules within my application itself, as administrators do not typically have access to Active Directory to maintain user rights therein.
I can't seem to find an OIDC pattern/workflow that addresses this use case. I was wondering if I could invoke the /authorize endpoint from my clients, but then pass the returned code into my existing Node server to invoke the /token endpoint. If that call was successful within Node then I thought I could keep building my custom JWT as I am now using a mix of information from my oAuth2 token/userinfo and the application database. I'm happy for my existing mechanisms to take care of token refreshes and revoking.
I think I'm making things harder by wanting to know my specific application claims within my client applications so that I can hide menu options. If it were just a case of protecting the API when called I'm guessing I could just do a lookup of permissions by sub every time a protected API was called.
I'm spooked that I can't find any posts of anyone doing anything similar. Am I missing the point of OIDC(to which I am very new!).
Thanks in advance...
Good question, because pretty much all real world authorization is based on domain specific claims, and this is often not explained well. The following notes describe the main behaviors to aim for, regardless of your provider. The Curity articles on scopes and claims provide further background on designing your authorization.
CONFIDENTIAL TOKENS
UIs can read claims from ID tokens, but should not read access tokens. Also, tokens returned to UIs should not contain sensitive data such as names, emails. There are two ways to keep tokens confidential:
The ID token should be a JWT with only a subject claim
The access token should be a JWT with only a subject claim, or should be an opaque token that is introspected
GETTING DOMAIN SPECIFIC CLAIMS IN UIs
How does a UI get the domain specific data it needs? The logical answer here is to send the access token to an API and get back one or both of these types of information:
Identity information from the token
Domain specific data that the API looks up
GETTING DOMAIN SPECIFIC CLAIMS IN APIs
How does an API get the domain specific data it needs from a JWT containing only a UUID subject claim? There are two options here:
The Authorization Server (AS) reaches out to domain specific data at the time of token issuance, to include custom claims in access tokens. The AS then stores the JWT and returns an opaque access token to the UI.
The API looks up domain specific claims when an access token is first received, and forms a Claims Principal consisting of both identity data and domain specific data. See my Node.js API code for an example.
MAPPING IDENTITY DATA TO BUSINESS DATA
At Curity we have a recent article on this topic that may also be useful to you for your migration. This will help you to design tokens and plan end-to-end flows so that the correct claims are made available to your APIs and UIs.
EXTERNAL IDENTITY PROVIDERS
These do not affect the architecture at all. Your UIs always redirect to the AS using OIDC, and the AS manages connections to the IDPs. The tokens issued to your applications are fully determined by the AS, regardless of whether the IDP used SAML etc.
You'll only get authentication from your OAuth provider. You'll have to manage authorization yourself. You won't be able to rely on OIDC in the SAML response or userinfo unless you can hook into the authentication process to inject the values you need. (AWS has a pre-token-gen hook that you can add custom claims to your SAML response.)
If I understand your current process correctly, you'll have to move the data you get from /userinfo to your application's database and provide a way for admins to manage those permissions.
I'm not sure this answer gives you enough information to figure out how to accomplish what you want. If you could let us know what frameworks and infrastructure you use, we might be able to point you to some specific tools that can help.
Ive been researching the MS Graph API lately, and I'm running into a problem. My use case is that I want to read a certain mailbox's mail, and send mail for that mailbox. The mailbox is a non user related box, and is used as a service account for emails.
Ive found 2 possible flows for getting into that mailbox. The user authenticated flow, and the application (and admin consented) flow. For the application, I want to read the emails in the background in a NodeJS app, without user interaction.
When I look into the user consented flow, I find that to make it work the user HAS to log in atleast once, by hand, and consent to some stuff I want to do. I found this page, on how this works, and made it work in my NodeJS app. The problem is, when using this flow, I have to login BY HAND atleast once after starting my NodeJS app. Afterwards I can use the refresh token to refresh the access token, but I dont want to do the login by hand.
The second option, and most suitable option for my NodeJS app, is the application flow. I found this tutorial on how to do that, and I made it all work. I fetch a token, and that token grants me access to the box via the Graph API.
But using the application flow, I found that I have to have the roles (i.e.): "User.ReadAll, Mail.Read, Mail.Send". This gives my application rights to read and send mail FOR ALL users in the account.. Which is WAY too much overkill for my situation.
Now my question; Is there a way for me to use MS Graph, with the application authentication flow, but without having access to all users' mailboxes, only to my specific account I want to read?
Thanks in advance,
Caspar
While linking the documentation reference, I saw that I read over the most important footnote:
Important Administrators can configure application access policy to limit app access to specific mailboxes and not to all the mailboxes in the organization, even if the app has been granted the application permissions of Mail.Read, Mail.ReadWrite, Mail.Send, MailboxSettings.Read, or MailboxSettings.ReadWrite.
So it is possible using the application access policies.
We are about to use Dynamics 365 CRM online and we are new in this area.
...User is logged in using SSO.
Now to my questions...
Alternative 1
Our solution architect want us to use a LogicApp, triggered by create/update on the contact entity, to pick up the loggedin users user access token and send it as Authorization header with the call to our onprem rest service.
As far as I can see this is not possible as the LogicApp is running in its own process (kind of as a windows service). Am I wrong?
We have been looking into other different options instead;
Alternative 2
We have been looking at using a Plugin but fails to get hold of the user access token. It is possible, though, to get hold of the application access token but that is not good enough for my client. Is it even possible? If possible, does anyone have an example of how it is done?
Alternative 3
We have been looking at using Javascript to trigger a LogicApp using HTTP request but fails on CORS. Would the user access token magically be sent with the call? Is it even possible? If possible, does anyone have an example of how it is done?
Alternative 4
We have been looking at using JavaScript but fails to get hold of the user access token. Is it even possible to do? If possible, does anyone have an example of how it is done?
We know how to get the user access token in a console application after logging in with SSO. And we know how to get the user access token in an ASPNET MVC application. But now... this is Dynamics 365 CRM online.
We need the user access token because we want the user information to be sent to API.
Are there any other options? We have been looking into this for a week or so...
In case there is anyone else that is looking into picking up the users access token from D365 online to send it along with calls to an onprem rest service I can now confirm that it is not possible (at least not for the moment).
Also, I have found out that what my customer really want to do is a mix of authentication/authorization and tracing.
Could you give a try by including powerapp which will call onpremAPI
I have to develop a SSO system and I have to do it using IdentityServer4. I have gone through the documentation and examples but I have some doubts. To be honest I don't quite get it, but I am really new in Oauth2 and OpenId Connect.
We will have a bunch of clients (web apps), each of one of those will have their own Web APi. And we have to have a centraliced Login App for all of those. I think the example with the javascript client is the closes to the thing we want to achieve. Also, a user might have permission to access one client (app), but not another, so the IdentityServer must provide information about wich clients (apps), that particularly user can access.
So, These are the things I don Understand:
1.- In the documentation I can read there are two tokens, an Identity Token and Access token. But in the examples all I see are the access tokens. It seems to me that the access token is the one with all de info needed. am I wrong?
2.- Also, I have read about de Grant Types and I'am not quite sure wich one we must use. At first I thought to use the ResourceOwner password, because it requires the client, the secret, a user and a password, wich I assumed it could be the end user. I found this example http://sunilrav.com/post/How-to-Customize-Authentication-in-Identity-Server-4 were one could customise the class that validate the user and password. I thought that this could be the way to go but the documentation statesa about this grant type "...This is so called “non-interactive” authentication and is generally not recommended.". The javascript client example uses the implicit Grat type, wich the documentation states is for browser-based applications (our client apps will all be browser based using react).
3.- can my Login app be a Javascript (react) app? The example Quickstart is made in MVC.NET. This login app connects directly to de IS4 server without asking for a access token? (In the example the app is embebed in the IS4).
4.- Can I protect with IS4 a WEB API which is developed in .net framework (4.6.2) and not in .Net Core? I havent Found Any examples.
the documentatios I followed is the offcial. The examples (quickstart) are also there. (I can't post more than two links).
thank you very much for reading and for your help.
Identity Token and Access token
Identity token is the one that contains the identity of the user, that will tell the client app that what user it is. After successful login, user will be redirected to the client app with these tokens. Response will also have claims, such as permission scopes, name , email you can add custom claims as well.
Access token is used to access your protected web api resource. You have to send the access token with each request to access the api.
Grant Types
Grant types is basically how you want your client app to interact with the auth server. https://identityserver4.readthedocs.io/en/release/topics/grant_types.html
can my Login app be a Javascript (react) app? Your client app can be a javascript app but your auth server that is the identity server which will have the login/signup pages(and other login jazz) and account controllers should be you MVC app. As, everything is already done using MVC and Entity framework, why you want to re do everything.
Can I protect with IS4 a WEB API I am not sure about this one, but I dont see why you would not be able to do it.
This is a good answer for basic IdSrv flow!
UPDATE In my understanding, the answer to which Grant Type to use it depends on your client application requirement. If you want to use a Javascript client you can use Implicit Flow, but you won't be able to use refresh tokens and your access token is not 100% secured with the browser as client can access it.
If you want to open your web api to public then you can use client credentials flow. If you want to be more secure you should use Hybrid flow or HybridClient credential flow. ( again depends on the requirements ). with this you will be able to use refresh tokens and in this way your access token would be more secure.
I'm in the process of building a Google Chrome extension, and have some questions about how to implement security into the application.
I need to access a couple of Google API's so am going to be using OAuth 2.0 for that. So basically from the extension I know which user is logged into the browser.
My extension then needs to get and post data to my (nodejs) API service. I want to ensure that the user requesting data is the same user that is logged into the browser. Is there any way of using the previous Google authentication process to also authenticate communications between the extension and my API? I dont really want the user to have to log in again, to access my API.
I'm sure I'm missing something simple, and I've not been able to find anything that fits this scenario
Follow the OpenID Connect auth flow and you will get an access_token and an id_token. The acess_token you will use to use to make authenticated requests to Google APIs as usual. The id_token will be used as authentication with requests to your server.
When the requests hit your server you will need to validate the token and you can then use the contents of the id_token to identify the user.
User wouldn't have to login on auth process provided if user is already logged in and you are using a web application flow (not chrome.identity APIs) but user would see the consent screen atleast the first time. However you can skip the account selector screen if you already know the email address by providing &login_hint= parameter.