-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathAuthController.cs
More file actions
96 lines (81 loc) · 3.67 KB
/
Copy pathAuthController.cs
File metadata and controls
96 lines (81 loc) · 3.67 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using AuthCodeWebAppMVC.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
namespace AuthCodeWebAppMVC.Controllers
{
public class AuthController : Controller
{
private readonly IConfiguration _configuration;
public AuthController(IConfiguration configuration)
{
_configuration = configuration;
}
private string ApiKey => _configuration["Secrets:ApiKey"];
private string ApiSecret => _configuration["Secrets:ApiSecret"];
// We hard-code the code_verifier here only for a simple example.
// A production app should be using newly-created values for each
// unique auth code flow attempt.
// See the PKCE RFC for specific information on this:
// https://tools.ietf.org/html/rfc7636#section-4.1
private const string CodeVerifier = "xnQ42e5Ee-fb17_47ad-A57f-903A_487a-81f9-63e701f7290f";
private const string RedirectUrl = Program.BaseUrl + "/Auth/Receiver";
[HttpGet]
public IActionResult StartAuthCodeFlow()
{
string codeChallenge = GetCodeChallenge();
string url =
$"https://authentication.gettyimages.com/oauth2/auth?client_id={ApiKey}&response_type=code&state=datasentfromclient&redirect_uri={System.Net.WebUtility.UrlEncode(RedirectUrl)}&code_challenge={codeChallenge}&code_challenge_method=S256";
return Redirect(url);
}
[HttpGet]
public async Task<IActionResult> Receiver(string code)
{
// Note: new-ing up an HttpClient like this should not be done in a production app. This is just to keep the example simple.
using (var client = new HttpClient())
{
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("client_id", ApiKey),
new KeyValuePair<string, string>("client_secret", ApiSecret),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", RedirectUrl),
new KeyValuePair<string, string>("code_verifier", CodeVerifier)
};
var req = new HttpRequestMessage(HttpMethod.Post, "https://authentication.gettyimages.com/oauth2/token")
{
Content = new FormUrlEncodedContent(formData)
};
var result = await client.SendAsync(req);
var content = await result.Content.ReadAsStringAsync();
var token = JsonSerializer.Deserialize<Token>(content);
return View(token);
}
}
private string GetCodeChallenge()
{
using (var sha = SHA256.Create())
{
var bytes = Encoding.ASCII.GetBytes(CodeVerifier);
var hash = sha.ComputeHash(bytes);
return Base64UrlEncode(hash);
}
}
// https://tools.ietf.org/html/rfc7636#appendix-A
private static string Base64UrlEncode(byte[] arg)
{
string s = Convert.ToBase64String(arg); // Regular base64 encoder
s = s.Split('=')[0]; // Remove any trailing '='s
s = s.Replace('+', '-'); // 62nd char of encoding
s = s.Replace('/', '_'); // 63rd char of encoding
return s;
}
}
}