.Net Core
-
Postgresql is used.
-
Imports
using System;
using System.Text;
using System.Text.Json;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using RestSharp;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Npgsql;
using System.Threading.Tasks;
- Constants
static string OIDC_AUTH_END_POINT = "https://tenantname.aws1.test1.com/auth/realms/{tenantname}/protocol/openid-connect/auth";
static string OIDC_CLIENT = "openidtestclient";
static string OIDC_CLIENT_SECRET = "0086d90a-221f-431c-ad35-741e6599bf6c";
static string OIDC_TOKEN_ENDPOINT = "https://tenantname.aws1.test1.com/auth/realms/{tenantname}/protocol/openid-connect/token";
- Generate Nonce
static string GenerateNonce(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-";
StringBuilder res = new StringBuilder();
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] uintBuffer = new byte[sizeof(uint)];
while (length --> 0)
{
rng.GetBytes(uintBuffer);
uint num = BitConverter.ToUInt32(uintBuffer, 0);
res.Append(valid[(int)(num % (uint)valid.Length)]);
}
}
return res.ToString();
}
- Datatypes
class OidcResponse
{
public string client_id { get; set; }
public string auth_url { get; set; }
public string composed_url { get; set; }
public OidcResponse(string client_id, string auth_url, string composed_url)
{
this.client_id = client_id;
this.auth_url = auth_url;
this.composed_url = composed_url;
}
}
class User
{
public string email { get; set; }
public User(string email) {
this.email = email;
}
}
class LoginResponse
{
public string token { get; set; }
public User user { get; set; }
public LoginResponse(string token, User user)
{
this.token = token;
this.user = user;
}
}
public class LoginData
{
public string code { get; set; }
public string redirect_uri { get; set; }
}
public class IdToken
{
public string id_token { get; set; }
}
/auth/oidc
(GET)
[HttpGet("oidc")]
public JsonResult GetOIDCURL([FromQuery(Name = "redirect_uri")] string redirect_uri)
{
string nonce = GenerateNonce(8);
string url = String.Format("{0}?client_id={1}&redirect_uri={2}&scope=openid&response_type=code&response_mode=query&nonce={3}", OIDC_AUTH_END_POINT, OIDC_CLIENT, redirect_uri,nonce);
var data = new OidcResponse(OIDC_CLIENT,OIDC_AUTH_END_POINT,url);
return new JsonResult(data);
}
/auth/code
(POST)
[HttpPost("code")]
async public Task<JsonResult> LoginWithCode([FromBody] LoginData loginData)
{
var client = new RestClient(OIDC_TOKEN_ENDPOINT);
var request = new RestRequest(Method.POST);
request.AddParameter("application/x-www-form-urlencoded", $"code={loginData.code}&client_id={OIDC_CLIENT}&grant_type={"authorization_code"}&client_secret={OIDC_CLIENT_SECRET}&redirect_uri={loginData.redirect_uri}", ParameterType.RequestBody);
var response = client.Post(request);
var content = JsonSerializer.Deserialize<IdToken>(response.Content);
var id_token = content.id_token;
if (!response.IsSuccessful || id_token == "")
{
BadRequest();
}
var handler = new JwtSecurityTokenHandler();
var decoded = handler.ReadJwtToken(id_token);
var email = (string)decoded.Payload["email"];
var user = _context.Find<User>(Guid.Parse(email));
if (user != null)
{
_context.Add(new User(email));
_context.SaveChanges();
}
var claimsIdentity = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Email, user.email)
});
var token = handler.CreateJwtSecurityToken("issuer", "audience", claimsIdentity, new DateTime(), new DateTime().AddHours(2), new DateTime(), new SigningCredentials(
new SymmetricSecurityKey(
Encoding.Default.GetBytes("secreasdasdtsecreasdasdtsecreasdasdtsecreasdasdtsecreasdasdtsecreasdasdtsecreasdasdt")),
SecurityAlgorithms.HmacSha256Signature));
var loginResponse = new LoginResponse(handler.WriteToken(token), user);
return new JsonResult(loginResponse);
}