I'm using IdentityServer4 and whenever the user login for the first time the application shows consent screen for the scopes of an application to the user which is expected. If the user clicks "yes" and click on remember option the application is not showing the consent screen when the user login for second time onwards which is also expected. Here the problem I'm facing is whenever I restart the IdentityServer (or when I do the deployment) the user consent information is not persisting and it is showing the consent screen again for the user. Can anyone help me to know Is there any way to store the user consent information into DataBase or how can we know where the information is being stored when the application is in running. I did some debugging but couldn't find it. Thanks in advance.
Add reference IdentityServer4.EntityFramework.Storage nuget package to identity server 4 project, Then in startup.cs
service.AddIdentityServer((options) => {})
.AddPersistedGrantStore<PersistedGrantStore>()
// Add other services.
The PersistedGrantStore requires PersistedGrantDbContext uses EntityFramework and requires the DbContext to be configured (same way you configure other EntityFramework DbContext). For example to use SQL Server
services.AddDbContext<PersistedGrantDbContext>(options =>
options.UseSqlServer(connectionString));
You can use dotnet-ef command tool to create and initialize the tables in the database.
You can also have your own implementation of IPersistedGrantStore service.
Related
The front end is already authenticated with Google/Facebook/Twitter.
I just need to use the id token from the front end to get the user profile info in the WebApi, check if we already have an account with that email etc. and if not then add the external login key to the Identity data (by calling AddLoginAsync on the Microsoft.AspNetCore.Identity.UserManager).
I don't want to hardcode the user profile endpoints for Google, Facebook etc. as they might change. I'd like to use something like a NuGet package that has these values and just update it when/if they change.
I've read a lot of examples but they're for whole authentication flows, using redirects and cookies in Asp.Net MVC... Although it seems basic, I didn't find an example where the external login is already done on the client and the backend just needs to use the resulting token to validate that login and get the user profile info.
Anyone else ran into this? Thanks!
I'm implementing Identity in ASP.NET Core 3 and having a bit of a problem understanding the flow of external login authentication, as are my users.
Things start clearly enough:
As expected I'm prompted to pick a Google identity:
Now at this point I'd expect to see a dialog such as the following, asking for permission to grant my app access to various pieces of the Google identity:
But that dialog never happens.
What does happen next is:
The above process step seems completely non-standard to any oauth flow I've ever seen. I've already given it which Google identity I'm using; the email address is unambigious. So this dialog seems extraneous and just confuses my users. Is there a reason for this step that I am not understanding?
...And back to the permission dialog above that I would have expected to get there, this never occurs. Why is the app able to accept a Google login without granting access via that dialog?
Why is the app able to accept a Google login without granting access via that dialog?
That seems Google will automatically grant OpenID Connect Scopes(openid profile email) after creating application . You can verify the scopes in console -->OAuth consent screen :
But if you want to also require additional sensitive scopes , you still need to grant permission dynamically during authentication :
services.AddAuthentication()
.AddGoogle(options =>
{
options.Scope.Add("https://www.googleapis.com/auth/gmail.modify");
options.Scope.Add("https://www.googleapis.com/auth/gmail.settings.basic");
options.ClientId = "xxxx";
options.ClientSecret = "xxxx";
});
Is there a reason for this step that I am not understanding?
That is because you enable the ASP.NET Core Identity. In asp.net core identity ,for external login ,after authentication , identity will help create a local user associated with external login user .After scaffolding Identity in ASP.NET Core projects , you could check the ExternalLogin.cshtml.cs file inside Areas/Identity/Pages/Account folder . In function OnGetCallbackAsync you will find identity will check the external login user information and confirm a local user is associated with external user , if yes , sign in user ; If no, it will redirect user to another page to ask the user to create an account in local database .
If you don't need that feature , just remove asp.net core identity or customize OnGetCallbackAsync function to skip the process .
I am building 2 MVC applications and will be using IdentityServer as a single sign-on authentication provider. By following the sample code from IdentityServer web site, I can get the authentication working. But now I am confused about how to register new users in the MVC applications.
For example in MVC 1, I have a secured controller action. Now accessing this action will be redirected to IdentityServer login page. If user selected an external login provider and login successfully, then the user will be redirected to the "Register" page of IdentityServer to ask whether the user wants to register. If user clicks "Register", then redirected to the secured action successfully. So far the sample code has done all these. But my question is that MVC1 & MVC2 need some more information about the user for registration. How can I prompt user to input these additional information? It is not feasible to have these information inputted in the IdentityServer register page because MVC 1 & 2 need different information. But if I have a register page in MVC1 & MVC2, then how can I force user to complete the registration? After user is authenticated from IdentityServer, he is returned directly to the originally requested Url. I just can't have code in every controller action to verify whether an authenticated user have completed the detailed registration.
An ideal way is that once a user is authenticated from IdentityServer, I can check whether this user has been registered in the local MVC user database. If not, then redirect the user to the local MVC register page and then back to the originally requested Url. How this can be done or is there a more appropriate way for doing this?
But my question is that MVC1 & MVC2 need some more information about
the user for registration.
To retrieve additional user info, you could depend on user claims for the additional user information. Otherwise, there is an endpoint called UserInfo Endpoint
But if I have a register page in MVC1 & MVC2, then how can I force
user to complete the registration?
Based on client_id you could change the registration view
I just can't have code in every controller action to verify whether an
authenticated user have completed the detailed registration.
You could create a customize filter to validate that. But, I would say try to keep the user related details on IdS4 project
I can check whether this user has been registered in the local MVC
user database. If not, then redirect the user to the local MVC
register page and then back to the originally requested Url. How this
can be done or is there a more appropriate way for doing this?
If you think, these user information will only be used for this client then you could take this approach.
However, if possible you asked for all the required details on the user registration page, no harms keeping the information for mvc1 users. But sometimes it is not possible (e.g. internal vs external users). If it is for internal users, then I guess it would be better to have a seperate Admin UI where user can add extra information.
Anyway, if you want to keep everything in one user registration page on Id server, i would add an extra flag on Client table which will indicate to show extra fileds. Hope this may help you.
I have a Xamarin Forms application that is targeting Windows UWP. I have successfully setup Offline Sync and Authentication by following the Microsoft docs such as this article: https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-windows-store-dotnet-get-started-users
I have also successfully setup a background (out-of-process) task to run using a Windows Universal Runtime Component.
The process flows as:
1) User runs the application for the first time, they must login and authenticate to Active Directory. The application then caches their token and registers the background task.
2) The background task kicks off on a Timer. During testing, I did NOT have it refreshing the token because I wanted to test the 1-hour token expiration and refresh process.
In my testing, I discovered two things that I am not completely understanding and which I found odd (not behaving as I expected).
1) When I examine the expiration date of the token the user receives upon first login, the expiration date is set for 30 days in the future. I thought it was supposed to expire after 1 hour. Why does it show 30 day expiration date? (This isn't too big of a concern as I did confirm that it does stop allowing access after an hour, just an oddity that I am observing).
2) This is the one I have a concern about. Even though the background task was not able to authenticate after the 1-hour period, it still was able to pull data from Azure to the device. The push data sync failed because authentication failed, but the pull data sync succeeded. This is concerning because I do not want unauthorized attempts to be able to pull data. Has anyone else ran into this? Is this a bug? Did I configure authentication incorrectly somehow?
My Settings:
Azure App Service > Easy Tables (Node.js backend) has all permissions set to "Authenticated Access only".
Azure App Service > Settings > Authentication/Authorization >
App Service Authentication is set to On,
Action to take when request is not authenticated is set to Log in with Azure Active Directory,
Authentication Providers is set Configured for Azure Active Directory.
Mobile App Code:
MobileServiceClient client;
IMobileServiceSyncTable<TableToPull> tableToPullDataFrom;
IMobileServiceSyncTable<TableToPush> tableToPushDataTo;
this.client = new MobileServiceClient(Constants.ApplicationURL);
this.client.CurrentUser = new MobileServiceUser(Settings.UserId);
this.client.CurrentUser.MobileServiceAuthenticationToken = Settings.AuthToken;
store.DefineTable<TableToPull>();
store.DefineTable<TableToPush>();
The Push Async Code is (which fails when authentication fails, as expected):
await this.client.SyncContext.PushAsync();
The Pull Async Code, which should fail when authentication fails but did not (this is my concern) is:
await this.tableToPullDataFrom.PullAsync("tableQuery",this.tableToPullDataFrom.CreateQuery());
I am concerned that the background task was able to pull data from Azure even though authentication failed. I am hopeful that I am misunderstanding this concept in some way and someone can explain to me why this happens? Or if I need to configure something differently? I need to make sure unauthorized logins cannot pull data.
The background task attempts to push and pull data in sequence and I can see that it fails due to invalid authentication during the push task but then succeeds during the pull task. I can also verify this because the pull task does grab updated data from the SQL Azure DB (I can view it using Isolated Storage Explorer and SQLite Browser) but it doesn't send changed data to the SQL Azure DB (viewed in SSMS).
The "action to take when authentication fails" is wrong. You need to set it to "No action". This is so that the authentication can be handled by your code.
If you are using Easy Tables, adjust the permissions on the table to "Authenticated". If you are using ASP.NET, add the [Authorize] attribute to your class.
Authentication is covered in depth in my book - chapter 2 of http://aka.ms/zumobook.
We are trying to build OAuth2 Authorization with IdentityServer3.
So we downloaded the Bytes from nuget and connected it with our database.
The database was initialized with the default scopes and the sample clients from Thinktecture self.
Then we connected AD FS as IDP via OWIN and made an simple ExternalUserService.
So far everything worked fine and the permissions page of the IdSrv could be opened, showing the username and that no application has consent up to now.
Then we tried to connect Xamarin.Auth to that and got an error Cannot determine application to sign in to and in the logs an error Signin Id not present (after logon at the ADFS IDP).
To reduce complexity, we decided to go back to the InMemoryUserService and created one InMemoryUser. This worked for the permissions page (at least for a short period of time - time is over now), but it did not allow OAuth2 Authorization Code Flow, which ended up in showing the login page again and again and again. And there is no evidence of any error in the logs.
How can we debug, what is happening? Is there any way to see, why a user gets redirected to the login page again despite being logged in?
--
We reduced the complexity even further by creating a new empty MVC application, which just uses a simple InMemoryUserFactory.
Now it's getting a little bit confusing: one user was able to logon from his machine - other machines (same user - since we created only one) are not able to login and get prompted with the login over and over again.
If using IdentityServer3 and you use own external login methods you should really pay close attention to the API of the IdSrv3.
We tried to create a login resutl with just the subject - this is made for local login on the server. If this is switched off at the same time, you will end up having problems.
So if you use an own external login provider and switch off local login, make sure to call the right overload for the authenticate method (3 Parameters in our case).