I'm looking for a way to silently verify that a user is still present in Active Directory after initially using AD to authenticate them.
My code for the user authentication looks like this:
var authenticateResult = await app.AcquireTokenAsync(settings.Scopes, username, UIBehavior.ForceLogin, "");
Where app is an instance of PublicClientApplication and username is a previously remembered username, if any, otherwise blank.
If this authentication succeeds, my app creates a persistent JWT token, stores it in local preferences, and uses that token for a long time (up to 60 days). If my app is closed and re-opened during that time, it re-uses the stored token and skips the AD authentication.
The problem I'm having is that my customer wants the app to check periodically (every hour or so) to ensure that the user's Active Directory access is still valid, and they want to do this without interrupting the user or presenting any UI. I tried using UIBehavior.NoPrompt, but that didn't work, I still got a prompt. I also tried using app.GetAccountAsync or GetAccountsAsync, since all I really need to do here is to ensure that the user's account still appears, but this doesn't work either (the calls return nothing).
I proposed to my customer that we simply lower the lifetime of the JWT token, but they don't want to do this. They want their users to be able to keep using the app for 60 days without logging in, unless they remove the user from AD during that time.
What's the best way to accomplish this?
The best way is to use refresh token.By default, access tokens expire after 1h. So it is recommended forcing a refresh every 30 min, or half the lifetime of the AT when this is a custom lifetime. The default value of refresh token is 90 days, 14 day inactive sliding .
So, If we want users to keep using the app for 60 days then we need o stop fetching refresh token on 60th day.
If we want to check user is in AAD programmatically. Then we can use MS Graph. Please go through Ms graph document for more details.
The C# code snippet is available below,
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var users = await graphClient.Users
.Request()
.GetAsync();
Ms Graph sample where we can test the above snippet is here.
Related
I am creating an electron application that connects to an Database and do POST and GET requests to retrieve and insert data into it, the problem is that in the code i have defined my database uri ( im using mongodb)
const uri = "mongodb+srv://<myusesrname>:<mypassword>#cluster0.wqbiu.mongodb.net/query?retryWrites=true&w=majority"
like in the example above, but if i pack my electron app the connection to the database as well as the credentials its visible if someone unpacks the app.asar file and look in the server.js file how i can solve this problem? i dont want any security breaches neither for me or the people that will be using my application, thanks in advance for any answer :)
An application that requires a secure connection to something cannot afford to have any username's or password's hardcoded into its code.
Instead, a procedure of authentication and authorisation is utilised.
Authentication is used to verify the user. IE: They are who they say they are, often achieved via the use of some type of login form.
Authorisation is used to verify the logged-in user is allowed to access the requested resource. EG: Is this user allowed to retrieve a list of all users email addresses from the database.
As a rough guide, a user will login with their username and password. You could use OpenID as well here if you wanted. Once the user is 'logged-in' you could set a cookie or session and save the session id in the DB against the user. Of course, all of this is done over HTTPS.
There are various ways to control the validity of the session such as but not limited to refreshing the expiration date / time every time the user hits the server, auto timeout if the user has not interacted with the server for more than X minutes, etc.
In your app, the user could try and interact with the database at any time, but if the user is not logged in, the server could return the appropriate response and prompt the user to login. Some form of API here is really the way to go.
If the user is logged in then then next step is to authorise the users request, ensuring they are allowed to perform what they are asking before sending a response back. If they are not authorised to access the resource (EG: Edit another user’s post) then an appropriate response is returned indicating so.
As you can see, securing your app will take some work but the result of not doing so could be devastating to you and your users.
I'd like to show a global activity feed and the counts of reactions to website visitors (without a user account). My app is using Firebase and React.
What I'd like to have:
Show a global feed (I'll do this by adding the activities with the "to:" field in each activity) and show it on the start page (no user accounts created so far, read-only)
Show the counts of likes for each activity (read-only)
As soon as someone clicks on the follow or like button, I'll require the user to sign in and create an account. The process after this step is straightforward to me. I'll use a Firebase function to create the auth token and use the client side React components to display the feeds and reactions.
I did not find a solution to show the global feed and the count of reactions to visitors who does not have a user auth token.
Some workarounds in my mind:
One approach would be to create an anonymous Firebase user and the Stream auth token for each website visitor. As soon as the user does an interaction I'd require him to create his account and upgrade the user's account using the Firebase migration process. This is pretty safe from a security perspective, but I would have a lot of anonymous users in the backend.
Another approach would be to create a global user and use the auth token to show the feed and likes. As soon as someone does an interaction I would require the user to login. Since no read-only Stream user accounts are available for the activity feed product, this might result in a security issue.
Do you have another solution in mind?
I've found a way to create read-only tokens for the client using the JWTScopeToken helper function. (Feed wide read-only tokens)
const streamSigner = require('getstream/lib/signing')
const apiSecret = '###APISECRET###'
const clientToken = streamSigner.JWTScopeToken(apiSecret, 'feed', 'read', {'feedId': '*', userId: "global"})
console.log("read-only client token for all feeds", clientToken)
Using this token a can show user and global feeds to new visitors. I do not have to create an anonymous user anymore.
What I'd like to do is end all sessions for a user when a user changes/resets their password (using ASP.NET Core Identity). I'm using the oidc-client-js library inside of a SPA. I've figured out how to end the current session for a user and cause any tabs that're in that same session (say, other tabs in the same browser windows) to recognize the session is over via the check session iFrame, but any other sessions (say in an incognito window) still seem to have the session functioning, even if their refresh tokens/all persisted grants for that subject ID have been revoked.
Is there some way to make that iFrame return to the client that the session is over for all sessions, like maybe have the iFrame page be checking the persisted grants for that session or something? I'm okay if a currently issued access_token continues working (they're short-lived), but just want the refresh tokens to be invalidated and the session to end.
Option 1
There is an OpenID Connect Session draft specification which would do what you want - it allows front end clients to check the current session state via an iframe. This is a draft and may not be implemented by ASP.NET Core Identity though.
https://openid.net/specs/openid-connect-session-1_0.html
Option 2
An alternative mechanism for resolving your problem programatically is by putting a check in your token exchange code. Your access tokens will presumably be relatively short lived, and so the front end has to regularly acquire new access tokens (either via refresh token, or by id token on the implicit flow for instance.
In your token exchange you could check for timestamp when the password was last updated.
If it is more recent than the timestamp when the token was issued, then instead of issuing the fresh access token you could return a 401 and manage a redirect to your authentication endpoint by a mechanism of your choice.
This doesn't instantly log the user out of alternative browser windows, because it depends upon the expiry window of your access tokens. If does have the advantage of working cross browser though, because it doesn't depend upon browser specific session information. It can also check for customers who are blacklisted, or who have changed their email address and other checks which might be relevant to a desire to force re-authentication.
For belt and braces you can use both these techniques.
I've been working with the Azure B2C for a couple of days now and have a few issues and questions:
Url that it creates to redirect for login is formed incorrectly. It contains a question mark twice - after the url, and again after the profile name. This causes a 404 not found error every time you login, log out, etc. For example, the URL it tries to redirect to for login looks like this: https://login.microsoftonline.com/samlmanbc.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_firstdemoprofile?client_id=08fcblahblah. You'll notice a second question mark after the profile name, and that's what breaks it.
If I fix that and try and log in, it doesn't recognize the username / password of my account that's a global admin. It DOES recognize the username / password of a new user I created locally in the directory.
In the OnRedirectToIdentityProvider method, when the request type is authentication, the AuthenticationResponseChallenge is null, which makes this call fail:
OpenIdConnectConfiguration config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary[Startup.PolicyKey]);
I worked around this by using the static string SignInPolicyId for the second parameter. That works fine when an account already exists, but if it doesn't then Azure fails at login and says an account doesn't exist for the user. So what is the right value to use there, and/or how does one initialize it so it isn't null?
The type of a claim that was added to a profile is preceded with "extension_"; is that always going to be true or just for now? For example, I added a property called "favoriteTeam", but the claim type for it is "extension_favoriteTeam".
When you use FaceBook as an identity provider, is there any way to pass along the Facebook access token claim (http://www.facebook.com/claims/AccessToken)? This was useful when using ACS with Facebook because your app can then use that token to make additional calls to Facebook to get data from it.
In relation to issue 1 - I updated my reference Microsoft.IdentityModel.Protocol.Extensions to v1.0.2.206221351 and it started working. I made some updates to other references before this, so if the first one doesn't work, try updating more assemblies from nuget.
This is as expected. A page that signs in "local account" users will not sign in your work or school account (in this case, the global admin user).
Always going to be true. We will be cleaning up the Admin UX to make this more clear.
This is on our roadmap. No ETA as yet.
I have a Asp.net MVC application that uses Azure AD and OpenID Connect OWIN middlewares to handle authentication. Everything works fine except for one thing : if a user is already logged-in on another Microsoft Application lets say a Office 365 account or maybe a live mail account, when trying to login it recives a page saying that it is not allowed to log into my app, which is correct, but some how I need to catch that situation in my code to allow the user to sign in with a different account. Is there a way of doing that? This is by design? I mean : the user have to log in only with a live/azure account at the time ? I couldn't find any documentation about this.
As of today there is typically one user at a time, but we will soon support for you a way to select a specific user instead of automatically signing you in with the most recent one.
One way you can work around this today is by injecting the parameter "prompt=login" in your sign in requests. You can do that in the RedirectToIdentityProvider notifications, similarly to what is showin in http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/ for domain_hint. This will cause the sign in experience to always start with a fresh prompt even if the user is already signed in. The draw back is that you'll never get SSO this way. Hopefully our account switiching feature will become available soon, keep an eye on http://blogs.technet.com/b/ad/ for announcements