public async Task <IActionResult> Authenticate([FromBody] AuthenticateRequest req) { repoContext.AuthCodes.ClearExpired(); // removed expired codes var code = req.Code; var auth = await repoContext.AuthCodes.FirstOrDefaultAsync(s => s.Code == code); if (auth == null) { return(NotFound(new { Error = "Code not found" })); } repoContext.AuthCodes.Remove(auth); var ghKey = auth.GitHubBearer; client.Credentials = new Credentials(ghKey); bool isNewUser = false; var ghUser = await client.User.Current(); var uid = ghUser.Id; var user = await repoContext.Users .Include(u => u.Groups) .ThenInclude(j => j.Group) .FirstOrDefaultAsync(u => u.GithubId == uid); if (user == null) { // if we can't find it, create a new user user = new Models.User { Name = ghUser.Login, Created = DateTime.Now, GithubId = ghUser.Id, GithubToken = ghKey }; repoContext.Users.Add(user); isNewUser = true; // TODO: do something different for default groups var defaultGroup = await repoContext.Groups .FirstOrDefaultAsync(g => g.Name == Group.DefaultGroupName); if (defaultGroup != null) { user.AddGroup(defaultGroup); } } else { // otherwise update token user.GithubToken = ghKey; } await repoContext.SaveChangesAsync(); var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(coreAuthSettings.JwtSecret); // TODO: figure out some way to do this that invalidates this token when the user's groups change var permClaims = user.GetPermissions().Select(p => new Claim(ClaimTypes.Role, p.ToString())); var descriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(permClaims.Prepend( new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())) .ToArray()), Expires = DateTime.Now + coreAuthSettings.JwtExpiry, SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) }; var jwt = tokenHandler.CreateToken(descriptor); return(Ok(new { Token = tokenHandler.WriteToken(jwt), IsNewUser = isNewUser })); }