Be Sociable, Share!

ASP.NET Identity 2.1 is the latest membership and identity management framework provided by Microsoft, this membership system can be plugged to any ASP.NET framework such as Web API, MVC, Web Forms, etc…

In this tutorial we’ll cover how to integrate ASP.NET Identity system with ASP.NET Web API , so we can build a secure HTTP service which acts as back-end for SPA front-end built using AngularJS, I’ll try to cover in a simple way different ASP.NET Identity 2.1 features such as: Accounts managements, roles management, email confirmations, change password, roles based authorization, claims based authorization, brute force protection, etc…

The AngularJS front-end application will use bearer token based authentication using Json Web Tokens (JWTs) format and should support roles based authorization and contains the basic features of any membership system. The SPA is not ready yet but hopefully it will sit on top of our HTTP service without the need to come again and modify the ASP.NET Web API logic.

I will follow step by step approach and I’ll start from scratch without using any VS 2013 templates so we’ll have better understanding of how the ASP.NET Identity 2.1 framework talks with ASP.NET Web API framework.

Setting up the ASP.NET Identity 2.1

Step 1: Create the Web API Project

In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, now create an empty solution and name it “AspNetIdentity” then add new ASP.NET Web application named “AspNetIdentity.WebApi”, we will select an empty template with no core dependencies at all, it will be as as the image below:

Step 2: Install the needed NuGet Packages:

We’ll install all those NuGet packages to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, as well we will install packages needed for ASP.NET Identity 2.1, if you would like to know more about the use of each package and what is the Owin server, please check this post.

Step 3: Add Application user class and Application Database Context:

Now we want to define our first custom entity framework class which is the “ApplicationUser” class, this class will represents a user wants to register in our membership system, as well we want to extend the default class in order to add application specific data properties for the user, data properties such as: First Name, Last Name, Level, JoinDate. Those properties will be converted to columns in table “AspNetUsers” as we’ll see on the next steps.

So to do this we need to create new class named “ApplicationUser” and derive from “Microsoft.AspNet.Identity.EntityFramework.IdentityUser” class.

Note: If you do not want to add any extra properties to this class, then there is no need to extend the default implementation and derive from “IdentityUser” class.

To do so add new folder named “Infrastructure” to our project then add new class named “ApplicationUser” and paste the code below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

publicclassApplicationUser:IdentityUser

{

[Required]

[MaxLength(100)]

publicstringFirstName{get;set;}

[Required]

[MaxLength(100)]

publicstringLastName{get;set;}

[Required]

publicbyteLevel{get;set;}

[Required]

publicDateTimeJoinDate{get;set;}

}

Now we need to add Database context class which will be responsible to communicate with our database, so add new class and name it “ApplicationDbContext” under folder “Infrastructure” then paste the code snippet below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

publicclassApplicationDbContext:IdentityDbContext<ApplicationUser>

{

publicApplicationDbContext()

:base("DefaultConnection",throwIfV1Schema:false)

{

Configuration.ProxyCreationEnabled=false;

Configuration.LazyLoadingEnabled=false;

}

publicstaticApplicationDbContext Create()

{

returnnewApplicationDbContext();

}

}

As you can see this class inherits from “IdentityDbContext” class, you can think about this class as special version of the traditional “DbContext” Class, it will provide all of the entity framework code-first mapping and DbSet properties needed to manage the identity tables in SQL Server, this default constructor takes the connection string name “DefaultConnection” as an argument, this connection string will be used point to the right server and database name to connect to.

The static method “Create” will be called from our Owin Startup class, more about this later.

Lastly we need to add a connection string which points to the database that will be created using code first approach, so open “Web.config” file and paste the connection string below:

Step 4: Create the Database and Enable DB migrations:

Now we want to enable EF code first migration feature which configures the code first to update the database schema instead of dropping and re-creating the database with each change on EF entities, to do so we need to open NuGet Package Manager Console and type the following commands:

1

2

enable-migrations

add-migrationInitialCreate

The “enable-migrations” command creates a “Migrations” folder in the “AspNetIdentity.WebApi” project, and it creates a file named “Configuration”, this file contains method named “Seed” which is used to allow us to insert or update test/initial data after code first creates or updates the database. This method is called when the database is created for the first time and every time the database schema is updated after a data model change.

As well the “add-migration InitialCreate” command generates the code that creates the database from scratch. This code is also in the “Migrations” folder, in the file named “<timestamp>_InitialCreate.cs“. The “Up” method of the “InitialCreate” class creates the database tables that correspond to the data model entity sets, and the “Down” method deletes them. So in our case if you opened this class “201501171041277_InitialCreate” you will see the extended data properties we added in the “ApplicationUser” class in method “Up”.

Now back to the “Seed” method in class “Configuration”, open the class and replace the Seed method code with the code below:

Now we are ready to trigger the event which will create the database on our SQL server based on the connection string we specified earlier, so open NuGet Package Manager Console and type the command:

1

update-database

The “update-database” command runs the “Up” method in the “Configuration” file and creates the database and then it runs the “Seed” method to populate the database and insert a user.

If all is fine, navigate to your SQL server instance and the database along with the additional fields in table “AspNetUsers” should be created as the image below:

Step 5: Add the User Manager Class:

The User Manager class will be responsible to manage instances of the user class, the class will derive from “UserManager<T>” where T will represent our “ApplicationUser” class, once it derives from the “ApplicationUser” class a set of methods will be available, those methods will facilitate managing users in our Identity system, some of the exposed methods we’ll use from the “UserManager” during this tutorial are:

Method Name

Usage

FindByIdAsync(id)

Find user object based on its unique identifier

Users

Returns an enumeration of the users

FindByNameAsync(Username)

Find user based on its Username

CreateAsync(User, Password

Creates a new user with a password

GenerateEmailConfirmationTokenAsync(Id)

Generate email confirmation token which is used in email confimration

SendEmailAsync(Id, Subject, Body)

Send confirmation email to the newly registered user

ConfirmEmailAsync(Id, token)

Confirm the user email based on the received token

ChangePasswordAsync(Id, OldPassword, NewPassword)

Change user password

DeleteAsync(User)

Delete user

IsInRole(Username, Rolename)

Check if a user belongs to certain Role

AddToRoleAsync(Username, RoleName)

Assign user to a specific Role

RemoveFromRoleAsync(Username, RoleName

Remove user from specific Role

Now to implement the “UserManager” class, add new file named “ApplicationUserManager” under folder “Infrastructure” and paste the code below:

As you notice from the code above the static method “Create” will be responsible to return an instance of the “ApplicationUserManager” class named “appUserManager”, the constructor of the “ApplicationUserManager” expects to receive an instance from the “UserStore”, as well the UserStore instance construct expects to receive an instance from our “ApplicationDbContext” defined earlier, currently we are reading this instance from the Owin context, but we didn’t add it yet to the Owin context, so let’s jump to the next step to add it.

Note: In the coming post we’ll apply different changes to the “ApplicationUserManager” class such as configuring email service, setting user and password polices.

Step 6: Add Owin “Startup” Class

Now we’ll add the Owin “Startup” class which will be fired once our server starts. The “Configuration” method accepts parameter of type “IAppBuilder” this parameter will be supplied by the host at run-time. This “app” parameter is an interface which will be used to compose the application for our Owin server, so add new file named “Startup” to the root of the project and paste the code below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

publicclassStartup

{

publicvoidConfiguration(IAppBuilder app)

{

HttpConfiguration httpConfig=newHttpConfiguration();

ConfigureOAuthTokenGeneration(app);

ConfigureWebApi(httpConfig);

app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

app.UseWebApi(httpConfig);

}

privatevoidConfigureOAuthTokenGeneration(IAppBuilder app)

{

// Configure the db context and user manager to use a single instance per request

What worth noting here is how we are creating a fresh instance from the “ApplicationDbContext” and “ApplicationUserManager” for each request and set it in the Owin context using the extension method “CreatePerOwinContext”. Both objects (ApplicationDbContext and AplicationUserManager) will be available during the entire life of the request.

Note: I didn’t plug any kind of authentication here, we’ll visit this class again and add JWT Authentication in the next post, for now we’ll be fine accepting any request from any anonymous users.

Define Web API Controllers and Methods

Step 7: Create the “Accounts” Controller:

Now we’ll add our first controller named “AccountsController” which will be responsible to manage user accounts in our Identity system, to do so add new folder named “Controllers” then add new class named “AccountsController” and paste the code below:

Our “AccountsController” inherits from base controller named “BaseApiController”, this base controller is not created yet, but it contains methods that will be reused among different controllers we’ll add during this tutorial, the methods which comes from “BaseApiController” are: “AppUserManager”, “TheModelFactory”, and “GetErrorResult”, we’ll see the implementation for this class in the next step.

We have added 3 methods/actions so far in the “AccountsController”:

Method “GetUsers” will be responsible to return all the registered users in our system by calling the enumeration “Users” coming from “ApplicationUserManager” class.

Method “GetUser” will be responsible to return single user by providing it is unique identifier and calling the method “FindByIdAsync” coming from “ApplicationUserManager” class.

Method “GetUserByName” will be responsible to return single user by providing it is username and calling the method “FindByNameAsync” coming from “ApplicationUserManager” class.

The three methods send the user object to class named “TheModelFactory”, we’ll see in the next step the benefit of using this pattern to shape the object graph returned and how it will protect us from leaking any sensitive information about the user identity.

Note: All methods can be accessed by any anonymous user, for now we are fine with this, but we’ll manage the access control for each method and who are the authorized identities that can perform those actions in the coming posts.

Step 8: Create the “BaseApiController” Controller:

As we stated before, this “BaseApiController” will act as a base class which other Web API controllers will inherit from, for now it will contain three basic methods, so add new class named “BaseApiController” under folder “Controllers” and paste the code below:

// No ModelState errors are available to send, so just return an empty BadRequest.

returnBadRequest();

}

returnBadRequest(ModelState);

}

returnnull;

}

}

What we have implemented above is the following:

We have added read only property named “AppUserManager” which gets the instance of the “ApplicationUserManager” we already set in the “Startup” class, this instance will be initialized and ready to invoked.

We have added another read only property named “TheModelFactory” which returns an instance of “ModelFactory” class, this factory pattern will help us in shaping and controlling the response returned to the client, so we will create a simplified model for some of our domain object model (Users, Roles, Claims, etc..) we have in the database. Shaping the response and building customized object graph is very important here; because we do not want to leak sensitive data such as “PasswordHash” to the client.

We have added a function named “GetErrorResult” which takes “IdentityResult” as a constructor and formats the error messages returned to the client.

Step 8: Create the “ModelFactory” Class:

Now add new folder named “Models” and inside this folder create new class named “ModelFactory”, this class will contain all the functions needed to shape the response object and control the object graph returned to the client, so open the file and paste the code below:

Notice how we included only the properties needed to return them in users object graph, for example there is no need to return the “PasswordHash” property so we didn’t include it.

Step 9: Add Method to Create Users in”AccountsController”:

It is time to add the method which allow us to register/create users in our Identity system, but before adding it, we need to add the request model object which contains the user data which will be sent from the client, so add new file named “AccountBindingModels” under folder “Models” and paste the code below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

publicclassCreateUserBindingModel

{

[Required]

[EmailAddress]

[Display(Name="Email")]

publicstringEmail{get;set;}

[Required]

[Display(Name="Username")]

publicstringUsername{get;set;}

[Required]

[Display(Name="First Name")]

publicstringFirstName{get;set;}

[Required]

[Display(Name="Last Name")]

publicstringLastName{get;set;}

[Display(Name="Role Name")]

publicstringRoleName{get;set;}

[Required]

[StringLength(100,ErrorMessage="The {0} must be at least {2} characters long.",MinimumLength=6)]

[DataType(DataType.Password)]

[Display(Name="Password")]

publicstringPassword{get;set;}

[Required]

[DataType(DataType.Password)]

[Display(Name="Confirm password")]

[Compare("Password",ErrorMessage="The password and confirmation password do not match.")]

publicstringConfirmPassword{get;set;}

}

The class is very simple, it contains properties for the fields we want to send from the client to our API with some data annotation attributes which help us to validate the model before submitting it to the database, notice how we added property named “RoleName” which will not be used now, but it will be useful in the coming posts.

Now it is time to add the method which register/creates a user, open the controller named “AccountsController” and add new method named “CreateUser” and paste the code below:

We validated the request model based on the data annotations we introduced in class “AccountBindingModels”, if there is a field missing then the response will return HTTP 400 with proper error message.

If the model is valid, we will use it to create new instance of class “ApplicationUser”, by default we’ll put all the users in level 3.

Then we call method “CreateAsync” in the “AppUserManager” which will do the heavy lifting for us, inside this method it will validate if the username, email is used before, and if the password matches our policy, etc.. if the request is valid then it will create new user and add to the “AspNetUsers” table and return success result. From this result and as good practice we should return the resource created in the location header and return 201 created status.

Notes:

Sending a confirmation email for the user, and configuring user and password policy will be covered in the next post.

As stated earlier, there is no authentication or authorization applied yet, any anonymous user can invoke any available method, but we will cover this authentication and authorization part in the coming posts.

Step 10: Test Methods in”AccountsController”:

Lastly it is time to test the methods added to the API, so fire your favorite REST client Fiddler or PostMan, in my case I prefer PostMan. So lets start testing the “Create” user method, so we need to issue HTTP Post to the URI: “http://localhost:59822/api/accounts/create” as the request below, if creating a user went good you will receive 201 response:

Now to test the method “GetUsers” all you need to do is to issue HTTP GET to the URI: “http://localhost:59822/api/accounts/users” and the response graph will be as the below:

In the next post we’ll see how we’ll configure our Identity service to start sending email confirmations, customize username and password polices, implement Json Web Token (JWTs) Authentication and manage the access for the methods.

Hi,
Do not try, ASP.NET 5 is a totally different platform, many things have changed especially when it comes to authentication and authorization, as well there is no middle ware for generating tokens until now. Web Apis will understand bearer tokens.
If you are referring to ASP.NET identity 3.0 then I didn’t play with it yet, so I have no comments yet.

Do you think you might have an update with ASP.NET 5 any time soon? I have a new project that I might try to move to 5 over the next 3-6 months depending on the release. Still trying to get better handle on ThinkTechture with ASP.NET Identity…Good example/walk through. Really helped me out. Thanks again.

What if we already have a database, and we want to create the Identity Pattern around it? Do we have to create all the fields in each table? (User, for example, has tens of fields: Phone Number, Email Confirmation etc., fields I may not need)
This is what I’m looking for as well…

Any idea why in the Seed method, when I tried to initialise the database with two users e.g. call manager.Create(user1, “password1”); manager.Create(user2, “password2”); it somehow only created the first user in the db?
Oh great series of posts by the way; this is exactly what I need though just get started trying myself.

Thanks for this tutorial; it’s hard to find a good guide that explains all of this without relying on the premade templates in VS.

I noticed the GET request for all users at the end of part 1 lists claims and roles in your example, and the GitHub project has those controllers in place. Did I miss an important step in this part, or are those pieces included later?

I had downloaded this project from Github its build successfully, when i send the request from PostMan my breakpoints hit on Account controller CreateUser method by using URL “http://localhost:59822/api/accounts/create”, but my CreateUser Method parameter “createUserModel” is null and received following exceptions

{
“message”: “An error has occurred.”,
“exceptionMessage”: “Object reference not set to an instance of an object.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” at AspNetIdentity.WebApi.Controllers.AccountsController.d__3.MoveNext() in C:\\AspNetIdentity.WebApi-master\\AspNetIdentity.WebApi\\Controllers\\AccountsController.cs:line 72\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”
}

I did not see any fields on PostMan where i fill data. Is there i missing something?

I followed this part of your tutorial step-by-step. However, I have tried testing the methods added to the API especially the ‘Create’ method using PostMan, but creating a user didn’t go well. I am getting the following error and I don’t know why.

{
“message”: “An error has occurred.”,
“exceptionMessage”: “Object reference not set to an instance of an object.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” at AspNetIdentity.WebApi.Controllers.AccountsController.d__3.MoveNext() in D:\\Practice\\AspNetIdentity\\AspNetIdentity.WebApi\\AspNetIdentity.WebApi\\Controllers\\AccountsController.cs:line 59\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”

Hi Taiseer, this is a great blog, I’m really new about web api and I want to lean more about it, also I want to do all yours tutorial becouse it seem great, but in this moment I have a problem when I do this : enable-migrations and add-migration InitialCreate and the error is the follow:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)

I don’t why, I need Sql Server 2012 Express for example?, can you help? please. sorry for the bad English.

Hi Ernesto, thanks for your message, can you check the connection string you used in webc.config, it seems you are not able to connect to the SQL express instance. If this didn’t work there are many other reasons for this, better to check answers on StackOverflow as this is a common issue.

I am running into an issue. I am trying to AppUserManager.AddClaimAsync(…) from within a WebApi controller but data is not persisted (saved) to DB unless Request.GetOwinContext().Get().SaveChanges() is called explicitly. Have you seen such behavior?

I see that Seed in DB Migration logic does not SaveChanges() explicitly … so where is difference coming from?

One thing I am struggling with is that I would like to find a user by a different field value such as AppUserManager.FindByPhoneNumberAsync(Id). However I am struggling to work out how to extend the AppUserManager. Any help would be very gratefully received.

First of all, this is a good article and it helps me a lot. I am now implemented it in my API project. now I have a requirement to integrate to some external authentication specifically LinkedIn but having trouble implementing it.

Thanks for the excellent tutorial. I really appreciate for all your efforts.
Actaully, I am eagerly waiting for the last section – “AngularJS Authentication and Authorization with ASP.NET Web API and Identity – Part 6”

Has anyone been able to get Refresh Tokens to work with this more recent tutorial (ASP.NET Identity 2.1 with ASP.NET Web API 2.2 (Accounts Management) ? I have tried following the earlier tutorials that included Refresh Tokens but I have not been able to figure out how to apply Refresh Tokens to this newer tutorial.

The older tutorials make use of a “AuthRepository” class but the newer version here seems to make use of “CustomOAuthProvider” class. I have not been able to figure out how to integrate the methods needed for Refresh Tokens into the CustomOAuthProvider. Any help someone could offer would be most welcome. Thank you!

but when the server starts, it complains about the two parameters “options and “Context” not being present.
Which is correct, the ApplicationUserManager Class has only one signature for the method “Create”, which needs options and Context as parameters.

I just ran into a scenario that I have not seen mentioned previously so I thought I’d ask about it.
If the username field contains an email address, neither of the functions GetUserByName or GetUserById are called. I receive a 404 error. I tried encoding the email field and it still returned a 404.
Just curious if anyone else has run into this previously and there is a known work around.
Thanks for the article it helped me greatly to quickly understand oauth.

Hello Mike,
What do you mean that method “GetUserByName” is not called? This is something you have control over, right? I do not think you need to encode anything as you are doing form post when you login and your are not sending the email in the URL, right?

Hi, I am facing this type of error. I tried to resolve it, but I can’t.

Error ‘Microsoft.Owin.IOwinContext’ does not contain a definition for ‘GetUserManager’ and no extension method ‘GetUserManager’ accepting a first argument of type ‘Microsoft.Owin.IOwinContext’ could be found (are you missing a using directive or an assembly reference?) C:\AspNetIdentity\Controllers\BaseApiController.cs

Could not load file or assembly ‘System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Please help i am getting the following error
The following errors occurred while attempting to load the app.
– No assembly found containing an OwinStartupAttribute.
– No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of “false” in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.

Hi Taiseer,
Thanks a lot for the tutorial.
I am unable to seed the database because of this line in the Configuration class
var manager = new UserManager(new UserStore(new ApplicationDbContext()));
and it says UserManager must be disposed for this code:” new UserManager(new UserStore(new ApplicationDbContext()));”

I am trying to the same approach and it is working file. When i am using Unity DI then there is problem with Microsoft.Owin.Host.SystemWeb package. If i uninstall this package, Unity works fine but startup didn’t load when application start. Please suggest how can i use identity with unity di.