Skip to content

Commit 5667848

Browse files
committed
refactor(file scoped namespace): Just added file scoped namespace and global.json
1 parent 5a09f79 commit 5667848

19 files changed

+646
-657
lines changed
Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
using System;
22
using System.Net;
33

4-
namespace ForceDotNetJwtCompanion
4+
namespace ForceDotNetJwtCompanion;
5+
6+
public class ForceAuthenticationException : Exception
57
{
6-
public class ForceAuthenticationException : Exception
7-
{
8-
public HttpStatusCode HttpStatusCode { get; }
8+
public HttpStatusCode HttpStatusCode { get; }
99

10-
public ForceAuthenticationException(HttpStatusCode statusCode, string description) : base(description)
11-
{
12-
HttpStatusCode = statusCode;
13-
}
10+
public ForceAuthenticationException(HttpStatusCode statusCode, string description) : base(description)
11+
{
12+
HttpStatusCode = statusCode;
1413
}
1514
}
Lines changed: 56 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,66 @@
11
using System;
22
using System.Threading.Tasks;
33

4-
namespace ForceDotNetJwtCompanion
4+
namespace ForceDotNetJwtCompanion;
5+
6+
/// <summary>
7+
/// IJwtAuthenticationClient
8+
///
9+
/// HTTP handling and orchestration of JWT OAuth Flow with Salesforce.
10+
///
11+
/// </summary>
12+
public interface IJwtAuthenticationClient : IDisposable
513
{
14+
string InstanceUrl { get; set; }
15+
string AccessToken { get; set; }
16+
string Id { get; set; }
17+
string ApiVersion { get; set; }
18+
619
/// <summary>
7-
/// IJwtAuthenticationClient
20+
/// JwtUnencryptedPrivateKeyAsync
821
///
9-
/// HTTP handling and orchestration of JWT OAuth Flow with Salesforce.
10-
///
22+
/// Obtain access token with unencrypted private key (not recommended)
23+
/// Token Endpoint: https://login.salesforce.com/services/oauth2/token (production)
1124
/// </summary>
12-
public interface IJwtAuthenticationClient : IDisposable
13-
{
14-
string InstanceUrl { get; set; }
15-
string AccessToken { get; set; }
16-
string Id { get; set; }
17-
string ApiVersion { get; set; }
18-
19-
/// <summary>
20-
/// JwtUnencryptedPrivateKeyAsync
21-
///
22-
/// Obtain access token with unencrypted private key (not recommended)
23-
/// Token Endpoint: https://login.salesforce.com/services/oauth2/token (production)
24-
/// </summary>
25-
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
26-
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
27-
/// <param name="username">Salesforce username</param>
28-
Task JwtUnencryptedPrivateKeyAsync(string clientId, string key, string username);
25+
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
26+
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
27+
/// <param name="username">Salesforce username</param>
28+
Task JwtUnencryptedPrivateKeyAsync(string clientId, string key, string username);
2929

30-
/// <summary>
31-
/// JwtPrivateKeyAsync
32-
///
33-
/// Obtain access token with encrypted private key
34-
/// Token Endpoint: https://login.salesforce.com/services/oauth2/token (production)
35-
/// </summary>
36-
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
37-
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
38-
/// <param name="passphrase">Passphrase of the private key</param>
39-
/// <param name="username">Salesforce username</param>
40-
Task JwtPrivateKeyAsync(string clientId, string key, string passphrase, string username);
30+
/// <summary>
31+
/// JwtPrivateKeyAsync
32+
///
33+
/// Obtain access token with encrypted private key
34+
/// Token Endpoint: https://login.salesforce.com/services/oauth2/token (production)
35+
/// </summary>
36+
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
37+
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
38+
/// <param name="passphrase">Passphrase of the private key</param>
39+
/// <param name="username">Salesforce username</param>
40+
Task JwtPrivateKeyAsync(string clientId, string key, string passphrase, string username);
4141

42-
/// <summary>
43-
/// JwtUnencryptedPrivateKeyAsync
44-
///
45-
/// Obtain access token with unencrypted private key (not recommended)
46-
/// with token endpoint
47-
/// </summary>
48-
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
49-
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
50-
/// <param name="username">Salesforce username</param>
51-
/// <param name="tokenEndpoint">TokenEndpointUrl e.g. https://test.salesforce.com/services/oauth2/token</param>
52-
Task JwtUnencryptedPrivateKeyAsync(string clientId, string key, string username, string tokenEndpoint);
42+
/// <summary>
43+
/// JwtUnencryptedPrivateKeyAsync
44+
///
45+
/// Obtain access token with unencrypted private key (not recommended)
46+
/// with token endpoint
47+
/// </summary>
48+
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
49+
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
50+
/// <param name="username">Salesforce username</param>
51+
/// <param name="tokenEndpoint">TokenEndpointUrl e.g. https://test.salesforce.com/services/oauth2/token</param>
52+
Task JwtUnencryptedPrivateKeyAsync(string clientId, string key, string username, string tokenEndpoint);
5353

54-
/// <summary>
55-
/// JwtPrivateKeyAsync
56-
///
57-
/// Obtain access token with encrypted private key
58-
/// with token endpoint
59-
/// </summary>
60-
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
61-
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
62-
/// <param name="passphrase">Passphrase of the private key</param>
63-
/// <param name="username">Salesforce username</param>
64-
/// <param name="tokenEndpoint">TokenEndpointUrl e.g. https://test.salesforce.com/services/oauth2/token</param>
65-
Task JwtPrivateKeyAsync(string clientId, string key, string passphrase, string username, string tokenEndpoint);
66-
}
67-
}
54+
/// <summary>
55+
/// JwtPrivateKeyAsync
56+
///
57+
/// Obtain access token with encrypted private key
58+
/// with token endpoint
59+
/// </summary>
60+
/// <param name="clientId">ClientId of the Connected App aka Consumer Key</param>
61+
/// <param name="key">Private key as string, it is not required to remove header and footer</param>
62+
/// <param name="passphrase">Passphrase of the private key</param>
63+
/// <param name="username">Salesforce username</param>
64+
/// <param name="tokenEndpoint">TokenEndpointUrl e.g. https://test.salesforce.com/services/oauth2/token</param>
65+
Task JwtPrivateKeyAsync(string clientId, string key, string passphrase, string username, string tokenEndpoint);
66+
}

ForceDotNetJwtCompanion/Jwt/Jwt.cs

Lines changed: 73 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,90 +3,89 @@
33
using ForceDotNetJwtCompanion.Models;
44
using ForceDotNetJwtCompanion.Util;
55

6-
namespace ForceDotNetJwtCompanion.Jwt
6+
namespace ForceDotNetJwtCompanion.Jwt;
7+
8+
/// <summary>
9+
/// Jwt
10+
/// Main class responsible for Salesforce JWT creation
11+
///
12+
/// It is basically a port of the Java example provided by Salesforce.
13+
/// Retrieving Modulus and Exponent from key files has been extracted to
14+
/// helper functions.
15+
///
16+
/// <see>https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5</see>
17+
///
18+
/// </summary>
19+
public class Jwt
720
{
8-
/// <summary>
9-
/// Jwt
10-
/// Main class responsible for Salesforce JWT creation
11-
///
12-
/// It is basically a port of the Java example provided by Salesforce.
13-
/// Retrieving Modulus and Exponent from key files has been extracted to
14-
/// helper functions.
15-
///
16-
/// <see>https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5</see>
17-
///
18-
/// </summary>
19-
public class Jwt
20-
{
21-
// Salesforce supports RS256 (no other algorithms are provided so far)
22-
private const string Header = "{\"alg\": \"RS256\"}";
23-
private JwtPayload _jwtPayload;
24-
private string _consumerKey; // aka ClientId
25-
private string _audience;
26-
private string _subject; // Salesforce user
27-
private string _expiration;
28-
private readonly PrivateKeyWrapper _privateKeyWrapper;
21+
// Salesforce supports RS256 (no other algorithms are provided so far)
22+
private const string Header = "{\"alg\": \"RS256\"}";
23+
private JwtPayload _jwtPayload;
24+
private string _consumerKey; // aka ClientId
25+
private string _audience;
26+
private string _subject; // Salesforce user
27+
private string _expiration;
28+
private readonly PrivateKeyWrapper _privateKeyWrapper;
2929

30-
private Jwt(PrivateKeyWrapper privateKeyWrapper)
31-
{
32-
_privateKeyWrapper = privateKeyWrapper;
33-
}
30+
private Jwt(PrivateKeyWrapper privateKeyWrapper)
31+
{
32+
_privateKeyWrapper = privateKeyWrapper;
33+
}
3434

35-
public static Jwt CreateJwt(PrivateKeyWrapper privateKeyWrapper) => new(privateKeyWrapper);
35+
public static Jwt CreateJwt(PrivateKeyWrapper privateKeyWrapper) => new(privateKeyWrapper);
3636

37-
public Jwt AddConsumerKey(string consumerKey)
38-
{
39-
_consumerKey = consumerKey;
40-
return this;
41-
}
37+
public Jwt AddConsumerKey(string consumerKey)
38+
{
39+
_consumerKey = consumerKey;
40+
return this;
41+
}
4242

43-
public Jwt AddAudience(string tokenEndpoint)
44-
{
45-
_audience = tokenEndpoint;
46-
return this;
47-
}
43+
public Jwt AddAudience(string tokenEndpoint)
44+
{
45+
_audience = tokenEndpoint;
46+
return this;
47+
}
4848

49-
public Jwt AddSubject(string subject)
50-
{
51-
_subject = subject;
52-
return this;
53-
}
49+
public Jwt AddSubject(string subject)
50+
{
51+
_subject = subject;
52+
return this;
53+
}
5454

55-
public Jwt AddExpiration(DateTime now)
56-
{
57-
_expiration = JwtHelpers.CreateExpTimeAsString(now);
58-
return this;
59-
}
55+
public Jwt AddExpiration(DateTime now)
56+
{
57+
_expiration = JwtHelpers.CreateExpTimeAsString(now);
58+
return this;
59+
}
6060

61-
public string Build()
62-
{
63-
if (
64-
string.IsNullOrEmpty(_consumerKey) ||
65-
string.IsNullOrEmpty(_expiration) ||
66-
string.IsNullOrEmpty(_subject) ||
67-
string.IsNullOrEmpty(_audience)
68-
) throw new ArgumentException("Missing arguments for JWT!");
61+
public string Build()
62+
{
63+
if (
64+
string.IsNullOrEmpty(_consumerKey) ||
65+
string.IsNullOrEmpty(_expiration) ||
66+
string.IsNullOrEmpty(_subject) ||
67+
string.IsNullOrEmpty(_audience)
68+
) throw new ArgumentException("Missing arguments for JWT!");
6969

70-
_jwtPayload = new JwtPayload
71-
{
72-
Aud = _audience,
73-
Exp = _expiration,
74-
Iss = _consumerKey,
75-
Sub = _subject
76-
};
70+
_jwtPayload = new JwtPayload
71+
{
72+
Aud = _audience,
73+
Exp = _expiration,
74+
Iss = _consumerKey,
75+
Sub = _subject
76+
};
7777

78-
var bytesToSign = Encoding.UTF8.GetBytes(
79-
string.Join(".",
80-
CommonHelpers.UrlEncode(Encoding.UTF8.GetBytes(Header)),
81-
_jwtPayload.ConvertToBase64())
82-
);
78+
var bytesToSign = Encoding.UTF8.GetBytes(
79+
string.Join(".",
80+
CommonHelpers.UrlEncode(Encoding.UTF8.GetBytes(Header)),
81+
_jwtPayload.ConvertToBase64())
82+
);
8383

84-
return string
85-
.Join(".",
86-
CommonHelpers.UrlEncode(Encoding.UTF8.GetBytes(Header)),
87-
_jwtPayload.ConvertToBase64(),
88-
CommonHelpers.UrlEncode(KeyHelpers.CreateSignature(_privateKeyWrapper, bytesToSign))
89-
);
90-
}
84+
return string
85+
.Join(".",
86+
CommonHelpers.UrlEncode(Encoding.UTF8.GetBytes(Header)),
87+
_jwtPayload.ConvertToBase64(),
88+
CommonHelpers.UrlEncode(KeyHelpers.CreateSignature(_privateKeyWrapper, bytesToSign))
89+
);
9190
}
9291
}
Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
using System;
22

3-
namespace ForceDotNetJwtCompanion.Jwt
3+
namespace ForceDotNetJwtCompanion.Jwt;
4+
5+
/// <summary>
6+
/// JwtHelpers
7+
///
8+
/// Helper functions for JWT creation
9+
///
10+
/// </summary>
11+
public static class JwtHelpers
412
{
513
/// <summary>
6-
/// JwtHelpers
7-
///
8-
/// Helper functions for JWT creation
14+
/// CreateExpTimeAsString
15+
/// Converts timestamp with TTL = 3 minutes
16+
/// You should use UTC time
17+
///
18+
/// <see>https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5</see>
919
///
1020
/// </summary>
11-
public static class JwtHelpers
12-
{
13-
/// <summary>
14-
/// CreateExpTimeAsString
15-
/// Converts timestamp with TTL = 3 minutes
16-
/// You should use UTC time
17-
///
18-
/// <see>https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5</see>
19-
///
20-
/// </summary>
21-
/// <param name="now"></param>
22-
/// <returns>epoc as string (seconds since 01.01.1970)</returns>
23-
public static string CreateExpTimeAsString(DateTime now) =>
24-
new DateTimeOffset(now.AddMinutes(3))
25-
.ToUnixTimeSeconds()
26-
.ToString();
27-
}
21+
/// <param name="now"></param>
22+
/// <returns>epoc as string (seconds since 01.01.1970)</returns>
23+
public static string CreateExpTimeAsString(DateTime now) =>
24+
new DateTimeOffset(now.AddMinutes(3))
25+
.ToUnixTimeSeconds()
26+
.ToString();
2827
}

0 commit comments

Comments
 (0)