forked from FortnoxAB/csharp-api-sdk
-
Notifications
You must be signed in to change notification settings - Fork 1
/
StandardAuthWorkflow.cs
129 lines (97 loc) · 4.91 KB
/
StandardAuthWorkflow.cs
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Fortnox.SDK.Connectors.Base;
using Fortnox.SDK.Serialization;
using Fortnox.SDK.Utility;
namespace Fortnox.SDK.Auth;
internal class StandardAuthWorkflow : BaseClient, IStandardAuthWorkflow
{
public const string AuthInitUri = "https://apps.fortnox.se/oauth-v1/auth";
public const string AuthTokenUri = "https://apps.fortnox.se/oauth-v1/token";
public ISerializer Serializer { get; internal set; }
public StandardAuthWorkflow()
{
Serializer = new JsonEntitySerializer();
}
public TokenInfo GetToken(string authCode, string clientId, string clientSecret, string redirectUri = null)
{
return GetTokenAsync(authCode, clientId, clientSecret, redirectUri).GetResult();
}
public async Task<TokenInfo> GetTokenAsync(string authCode, string clientId, string clientSecret, string redirectUri = null)
{
if (string.IsNullOrEmpty(authCode))
throw new ArgumentException("Argument is null or empty.", nameof(authCode));
if (string.IsNullOrEmpty(clientId))
throw new ArgumentException("Argument is null or empty.", nameof(clientId));
if (string.IsNullOrEmpty(clientSecret))
throw new ArgumentException("Argument is null or empty.", nameof(clientSecret));
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
var request = new HttpRequestMessage(HttpMethod.Post, AuthTokenUri);
request.Headers.Add("Authorization", $"Basic {credentials}");
var parameters = new Dictionary<string, string>();
parameters.Add("grant_type", "authorization_code");
parameters.Add("code", authCode);
if (redirectUri != null)
parameters.Add("redirect_uri", redirectUri);
request.Content = new FormUrlEncodedContent(parameters);
var responseData = await SendAsync(request).ConfigureAwait(false);
var responseJson = Encoding.UTF8.GetString(responseData);
var tokenInfo = Serializer.Deserialize<TokenInfo>(responseJson);
return tokenInfo;
}
public TokenInfo RefreshToken(string refreshToken, string clientId, string clientSecret)
{
return RefreshTokenAsync(refreshToken, clientId, clientSecret).GetResult();
}
public async Task<TokenInfo> RefreshTokenAsync(string refreshToken, string clientId, string clientSecret)
{
if (string.IsNullOrEmpty(refreshToken))
throw new ArgumentException("Argument is null or empty.", nameof(refreshToken));
if (string.IsNullOrEmpty(clientId))
throw new ArgumentException("Argument is null or empty.", nameof(clientId));
if (string.IsNullOrEmpty(clientSecret))
throw new ArgumentException("Argument is null or empty.", nameof(clientSecret));
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
var request = new HttpRequestMessage(HttpMethod.Post, AuthTokenUri);
request.Headers.Add("Authorization", $"Basic {credentials}");
var parameters = new Dictionary<string, string>();
parameters.Add("grant_type", "refresh_token");
parameters.Add("refresh_token", refreshToken);
request.Content = new FormUrlEncodedContent(parameters);
var responseData = await SendAsync(request).ConfigureAwait(false);
var responseJson = Encoding.UTF8.GetString(responseData);
var tokenInfo = Serializer.Deserialize<TokenInfo>(responseJson);
return tokenInfo;
}
public string GenerateState()
{
var data = new byte[32];
using var rng = new RNGCryptoServiceProvider();
rng.GetBytes(data);
var state = Convert.ToBase64String(data).Replace('+', '-').Replace('/', '_').TrimEnd('=');
return state;
}
public Uri BuildAuthUri(string clientId, IEnumerable<Scope> scopes, string state, string redirectUri = null)
{
if (string.IsNullOrEmpty(clientId))
throw new ArgumentException("Argument is null or empty.", nameof(clientId));
if (string.IsNullOrEmpty(state))
throw new ArgumentException("Argument is null or empty.", nameof(state));
var parameters = new Dictionary<string, string>();
parameters.Add("client_id", clientId);
if (redirectUri != null)
parameters.Add("redirect_uri", redirectUri);
parameters.Add("scope", string.Join(" ", scopes.Select(s => s.GetStringValue())));
parameters.Add("state", state);
parameters.Add("access_type", "offline");
parameters.Add("response_type", "code");
var query = string.Join("&", parameters.Select(p => $"{p.Key}={Uri.EscapeDataString(p.Value)}"));
var uri = string.Join("?", AuthInitUri, query);
return new Uri(uri);
}
}