/// <summary> /// Gets the user information synchronous. /// this is triggered when a user makes a request who does not have an account already. /// </summary> /// <param name="actionContext">The action context.</param> /// <param name="config">The configuration.</param> /// <returns>The user object with information retrieved from the identity server</returns> public static UserCreateInternalResource GetUserInformation(this HttpContext actionContext, Config config) { string bearerToken = actionContext.Request.Headers.GetCommaSeparatedValues("Authorization") .FirstOrDefault(); string providerId = ""; if (bearerToken != null) { string token = bearerToken.Replace("Bearer ", ""); JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); if (handler.ReadToken(token) is JwtSecurityToken tokens) { providerId = tokens.Claims.FirstOrDefault(claim => claim.Type == "idp") ?.Value; } } if (string.IsNullOrEmpty(bearerToken)) { return(null); } // Not sure maybe has to be retrieved from the originating identity server aka from the token iss. RestClient client = new RestClient(config.IdentityServer.IdentityUrl + "/connect/userinfo"); RestRequest request = new RestRequest(Method.POST); request.AddHeader("Authorization", bearerToken); IRestResponse response = client.Execute(request); JObject jsonResponse = JsonConvert.DeserializeObject <JObject>(response.Content); if (jsonResponse?.ContainsKey("name") != true || jsonResponse?.ContainsKey("email") != true || jsonResponse?.ContainsKey("sub") != true) { return(null); } UserCreateInternalResource newUser = new UserCreateInternalResource { Name = (string)jsonResponse["name"], Email = (string)jsonResponse["email"], IdentityId = (string)jsonResponse["sub"], IdentityInstitutionId = providerId }; return(newUser); }
/// <summary> /// Configures the specified application. /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. /// </summary> /// <param name="app">The application.</param> /// <param name="env">The env.</param> public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { env.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "Uploads"); Defaults.Path.filePath = Path.Combine(env.WebRootPath, "Images"); UpdateDatabase(app, env); if (env.IsDevelopment()) { //app.UseBrowserLink(); app.UseDeveloperExceptionPage(); //app.UseDatabaseErrorPage(); } else if (env.IsProduction()) { app.UseExceptionHandler(new ExceptionHandlerOptions { ExceptionHandler = context => { context.Response.ContentType = "text/HTML"; context.Response.Redirect("/Error.html"); return(Task.CompletedTask); } }); } else { app.UseExceptionHandler(); } app.UseProblemDetails(); app.UseStaticFiles(); app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider( Path.Combine(env.ContentRootPath, "Uploads", "Images")), RequestPath = "/Uploads/Images" }); app.UseRouting(); app.UseCors(c => { c.WithOrigins(Config.Frontend.FrontendUrl); c.SetIsOriginAllowedToAllowWildcardSubdomains(); c.AllowAnyHeader(); c.AllowAnyMethod(); }); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); //UserInfo app.UseWhen(context => context.User.Identities.Any(i => i.IsAuthenticated), appBuilder => { appBuilder.Use(async(context, next) => { DbContext dbContext = context.RequestServices.GetService <DbContext>(); IUserService userService = context.RequestServices.GetService <IUserService>(); string identityId = ""; try { identityId = context.User.GetIdentityId(context); } catch (UnauthorizedAccessException e) { Log.Logger.Error(e, "User is not authorized."); await next(); } IInstitutionService institutionService = context.RequestServices.GetService <IInstitutionService>(); UserCreateInternalResource userInformation = context.GetUserInformation(Config); User user = await userService.GetUserByIdentityIdAsync(identityId) .ConfigureAwait(false); if (user == null) { IRoleService roleService = context.RequestServices.GetService <IRoleService>(); Role registeredUserRole = (await roleService.GetAll()).FirstOrDefault( i => i.Name == nameof(Defaults.Roles.RegisteredUser)); if (userInformation == null) { // Then it probably belongs swagger so we set the username as developer. User newUser = new User { Name = "Developer", Email = "*****@*****.**", IdentityId = identityId, Role = registeredUserRole, InstitutionId = 1 }; userService.Add(newUser); } else { User newUser = new User { Name = userInformation.Name, Email = userInformation.Email, IdentityId = userInformation.IdentityId, Role = registeredUserRole, }; Institution institution = await institutionService.GetInstitutionByInstitutionIdentityId( userInformation.IdentityInstitutionId); if (institution != null) { newUser.InstitutionId = institution.Id; } userService.Add(newUser); } await dbContext.SaveChangesAsync() .ConfigureAwait(false); } // If the user is already in the database and the Update institution on login is set to true else if (Config.OriginalConfiguration.GetValue <bool>("UpdateInstitutionOnLogin")) { if (userInformation != null) { Institution institution = await institutionService.GetInstitutionByInstitutionIdentityId( userInformation.IdentityInstitutionId); if (institution != null) { user.InstitutionId = institution.Id; } userService.Update(user); await dbContext.SaveChangesAsync() .ConfigureAwait(false); } } await next() .ConfigureAwait(false); }); }); app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); app.UseSwagger(); app.UseSwaggerUI(o => { o.SwaggerEndpoint("/swagger/v1/swagger.json", "Dex API V1"); o.DocExpansion(DocExpansion.None); o.RoutePrefix = ""; o.DisplayRequestDuration(); o.OAuthClientId(Config.Swagger.ClientId); }); }