Should I Create only one client and all my applications must connect to the identity server using it or there is configuration should I do to make it work?
Identity Server is Web API, grant type is "resource owner password".
Each application is a client. But whether you should use the same client_id is up to you. Personally I use different client_id's for each instance of an application. This helps me to identify the instance and allows me to use different secrets per instance. And I think that the client_id has to be unique when you are using refresh tokens.
SSO is something you get for free when you use OpenId Connect (oidc). It works because of a cookie on the IdentityServer website:
When a user has to log in, the user is redirected to the IdentityServer website where (after succesful authentication) a cookie is set, containing information about the identity of the user.
When the user is returned to the client (after succesful authentication) the client will also set a cookie. As long as this authentication cookie is available, the user will be logged in.
When the user needs to log in again, because the client can't authenticate the user (anymore), IdentityServer will try to identify the user with the information from the cookie on the IdentityServer website and (if succesful) automatically sign in the user, skipping the login form.
But it seems that your setup has nothing to do with oidc. When you say that IdentityServer is a Web Api then this suggests that the user is not redirected to the IdentityServer to login, meaning that there is no opportunity to set a cookie.
And Resource Owner Password Credentials (ROPC) is an OAuth2 grant type. This suggests that the user performs the login on the client.
In order to enable SSO, the user has to login on the IdentityServer website. While ROPC is still possible, you'd better use one of the recommended grant types.
Related
The flow I am trying to figure out is this:
UserA is logs into ClientA
ClientA redirects to Idenitity Server to authenticate user
after authentication ClientA manages User info in its own system
UserA is found to be a "bad actor"
AdminUser goes into IdentityServer AdminTool (a different client application for managing the IdentityServer, including users).
AdminUser performs an action to "revoke" UserA
A call is made to the IdentityServer back-end from the admin tool where UserA has an "Enabled" property that is set to false.
At this point in the flow I want to kick the user out of ClientA from the back-end of the IdentityServer.
More context:
IdentityServer is using cookies in the client browser to keep the "session" (not sure if that is the right word cause there isn't actually any state being managed).
Also using cookies for remember-me.
Is there a way to remove the cookie for the IdentityServer from the back-end? Or notify the client that UserA should no longer have a valid authentication so that it can perform HttpContext.SignOutAsync()?
I was reviewing this link: https://docs.identityserver.io/en/latest/topics/signout.html for guidance but I am stuck on how to do this from the back-end as the AdminUser. Calling HttpContext.SignOutAsync() would sign out the AdminUser that made the request, not UserA that is causing havok in ClientA.
In a typical setup with identity server you have:
A JWT token with a short lifetime
A session cookie
The JWT token needs to be renewed frequently. The session cookie is used when there's no valid JWT. In this case the user will be redirected to the login page and if there's a session cookie the user will be automatically authenticated and redirected back to client app.
So you have some options for your logout:
Ensure the user cannot renew his JWT (= logout after a few minutes)
Ensure the user cannot login again
Really clear everything in the browser (and ensure he cannot login/renew again)
Back to your question
Is there a way to remove the cookie for the IdentityServer from the back-end?
The answer here is WebSockets which allows a two-way communication.
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
A common library for C# is Signal/R
https://dotnet.microsoft.com/apps/aspnet/signalr
You would create a Hob on the server side that allows you to send messages to the "bad user".
https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-6.0
And listen for those messages in your client app:
https://learn.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0
Please note: Whatever you do on the client side, the important part is typically to block the server requests. It's not secure to delete the cookie on the client. You have to delete the session on the server side instead.
Additional notes:
The flows in your setup may be different from what I described above.
I know, this is just a partial answer, but it's too much content for a comment ;-)
While SSO is enabled for an organization, can an API account still use Legacy Authentication (username/password still being used for this account) on behalf of a user that has SSO enabled?
Our company wants to transition to using SSO for all user accounts (except possibly the API account). Currently, we use DocuSign's Legacy Authentication header (X-DocuSign-Authentication) to send envelopes on behalf of users and create sender views for them. Both of these actions involve using our API account's username and password for authentication on behalf of a user.
I've read this post that says:
If you're using Legacy Header authentication, your application won't
be able to authenticate as users who have SSO Login enforced. Until
you're able to implement one of the OAuth workflows, users who need to
use your API integration will need to have their Login Policy set to
allow them to login with a password.
Does this mean that any user account that will be sent on behalf of them will need to have SSO disabled while the Legacy Authentication header (and API account using username/password) is being used?
In addition, we are trying to avoid having every user separately authorize the application to act on their behalf. This post seems to mention there is a way to avoid that. Both the Authorization Code Grant and JWT Grant state that you must get your user's consent. We want to avoid this since we have 100's of members and staff additional staff added frequently.
Optimally, we would like to keep the API things as they are. If we can't or shouldn't, what changes do we have to make?
If SSO is enabled, a user can still authenticate via their DocuSign password, and thus Legacy Header auth will still work. If SSO Authentication is made mandatory via Login Policy settings, the user cannot authenticate with their DocuSign password, and Legacy Header auth will break.
If your authenticating "system sender" user has SSO optional, the SendOnBehalfOf header can be used to impersonate anyone on the account, regardless of the other user's Login Policy settings.
If you have a Claimed Domain, you can grant Admin consent so that all users with email addresses under that claimed domain (current and future) will not be required to grant individual consent for JWT impersonation. More information on that is available here: https://www.docusign.com/blog/developers/oauth-jwt-granting-consent
I am trying to better understand the OpenID Connect protocol with IdentityServer4, and am unclear on where I can find the answer to this question.
I like the idea of the Identity Server providing a Bearer Token at the end of authentication that includes claims on who the user is, and what resources they can access. However, I am a little uncomfortable in storing what Resources a user may have access to within the Identity Server environment. I would like this Authorization piece to be authored at my client application. Is there any type of callback in the OpenID callback that allows IdentityServer to call the client and request Authorization Claims from the client directly, rather than piece it together directly?
As an example, I am working on a product that will require a user to log in using either Windows Authentication, Username/Password, or a Google Account.
This client application will be hosted in a cloud environment, and will be hosted in the same domain as the Active Directory Server.
My thought was to create an Identity Server solution that is hosted internally, and to create a Client application that is hosted in the cloud.
When the user logs into the Client application, they would be redirected to the Identity Server to log in. The Identity Server would be hosted in the same domain as the Active Directory Server, so if there were Windows Credentials we could log them in automatically. Otherwise, there will be a login screen where they can enter a Username/Password, log in with Google, etc.
Once the user has logged in, the Identity Server would return a Bearer Token (a JWT probably), that has their claim information.
I can foresee this one Identity Server being used by many different Client application, because it would intrinsically allow Windows Authentication. For this reason, I am hesitant to store all of the API Resources the user can access within the Identity Server itself. My fear is that if I add a new permission to my client application (like a Report Admin claim), I would need to modify the Identity Server to include that new claim. And if 4 or 5 clients all use this Identity Server, this could get to be a bit onerous.
Instead, I would like to structure Identity Server so that when a user logs in for a particular client, Identity Server will make a callback request to the Client Application asking for the Claims that apply to that user. That way, the Client Application knows and cares about the User/Claim mappings, not the Identity Server. If I need to add a new Claim, I can do that within the Client application. If I need to map a user to a Claim, I can do that on the Client application. I don't need to do this on the Identity Server.
Is this functionality that already exists? If so, what do I need to be looking for? From what I can tell, it appears that the mapping between the User and the Resources they have access to all occur on the Identity Server.
The guide I am following is this: http://docs.identityserver.io/en/release/quickstarts/1_client_credentials.html#defining-the-api
Thank you for any guidance.
The Identity claims are not supposed to be used for Authorization, in fact Authentication and Authorization are two totally different concerns.
I'd suggest you watch this video which explains why and also provides an alternative PolicyServer that would answer your questions (great talk from the developers of IdentityServer).
I have portal A for which I've implemented SAML authentication with an SP (Azure AD). In portal A, I will show some screens from Portal B as Iframe.
Both portal A and portal B uses SAML based authentication from the same IDP (Azure AD).
Situation here is users login into Portal A and when tried to access pages where Portal B screens are shown as Iframes, they have to initiate a SAML login again (However they are not prompted to enter their credentials now
as they are already logged into Portal A using SAML authentication)
I was initially under the impression that when Portal A is authenticated against IDP, this will establish an SSO against all the portals which uses the same IDP for authentication. But now I understand that it is not how it works.
Is it possible to achieve SSO for all SP's which uses the same IDP for authentication when the user has successfully authenticated himself with one SP need not be prompted to login for all other SP's using samle IDP's?
There is an isPassive option in the SAML authentication request that allows the SP to check whether the user is authenticated at an IDP without any interaction with the user, regardless of the status (i.e. authenticated vs. unauthenticated). See https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf section 3.4.1:
IsPassive [Optional]
A Boolean value. If "true", the identity provider
and the user agent itself MUST NOT visibly take control of the user
interface from the requester and interact with the presenter in a
noticeable fashion. If a value is not provided, the default is
"false".
A SP could use that in an iframe that does not display to the user to find out whether to pop the "Login" button or not. If the user is authenticated a SAML response will be returned without bothering the user and an application session can be created. If the user is not authenticated, the SAML response will indicate that and the "Login" button can be shown.
This does rely on the fact that the SP knows which IDP to ask.
There is no standardized way to logon the user to all SPs in one go but the IDP could implement such functionality in something like an enterprise portal that launches iframes to the SP with IDP-initiated-SSO SAML responses.
My ASP.NET MVC 4 application is protected by SSO (OAM) with an ISAPI filter running on IIS. When a request to my application is received, it is intercepted by ISAPI filter and redirected to SSO. User has to login at SSO and after that he is returned to my application.
The username of authenticated user (via SSO) is shared with my application in HTTP Request Headers.
Request.Headers["username"]
What I am trying to achieve is- after SSO authentication, setting FormsAuthentication within my application for username = Request.Headers["username"]. This way SSO remains transparent to my application and Identity of user is available in HttpContext object, plus, I (developer) could effectively utlize Authorize attribute for specific roles.
To achieve this- I hookup into Session_Start(), read Request.Headers["username"], Set FormsAuthentication cookie. And I get this SSO user Forms-Authenticated for my application.
But my problem is when I logout (FormsAuthentication.Signout), I redirect it to another page inside the application, which triggers a new Session (I can see Session_Start triggering when this happens)
Am I doing the right thing- FormsAuthentication after SSO? And if not, why not and then how do I make my application aware of SSO authenticated user?
It's entirely reasonable to use FormsAuthentication cookies to track the logged in user in your application after they have been authenticated using a Single-Sign-On provider. You don't show it but I'm hoping that you are also getting some ticket that you can use to verify the signed in user out-of-band with the SSO provider and not simply trusting the username header.
What you may be seeing, however, is that the user is not signed out from the SSO provider when you sign them out of your application. Because of that, as long as they have a valid cookie for the SSO provider, they will remain signed in, i.e., the user will get automatically bounced back to your application from the SSO provider without any required authentication.
That's unfortunate, but normal.
If you truly want the user to be signed out, you'll need to make use of the centralized logout functionality. I haven't worked with OAM, but it appears that it does support this: http://docs.oracle.com/cd/E21764_01/doc.1111/e15478/logout.htm
I had to explicitly kill the session inside Session_Start if requested URL is logout URL. And then with next request (like from logout to login page again), it generates a new session and runs smoothly.
protected void Session_Start()
{
if (!Request.IsAuthenticated && !IsSignoutURL)
AcceptSessionRequest(); //process local authentication
else if (IsSignoutURL)
RejectSessionRequest(); //kill the sessions
}
For background on how SSO passes authenticated user's identity to my application, read my comment to tvanfosson's post.
The post remains opened for a better idea.