1
1
2
2
using Microsoft . AspNetCore . Authentication ;
3
3
using Microsoft . Extensions . Options ;
4
- using rubberduckvba . Server . Api . Admin ;
5
4
using rubberduckvba . Server . Services ;
6
5
using System . Security . Claims ;
7
- using System . Security . Cryptography ;
8
- using System . Text ;
9
6
using System . Text . Encodings . Web ;
10
7
11
8
namespace rubberduckvba . Server ;
@@ -35,79 +32,3 @@ protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
35
32
: AuthenticateResult . NoResult ( ) ;
36
33
}
37
34
}
38
-
39
- public class WebhookAuthenticationHandler : AuthenticationHandler < AuthenticationSchemeOptions >
40
- {
41
- private readonly ConfigurationOptions _configuration ;
42
-
43
- public WebhookAuthenticationHandler ( IOptionsMonitor < AuthenticationSchemeOptions > options , ILoggerFactory logger , UrlEncoder encoder ,
44
- ConfigurationOptions configuration )
45
- : base ( options , logger , encoder )
46
- {
47
- _configuration = configuration ;
48
- }
49
-
50
- protected async override Task < AuthenticateResult > HandleAuthenticateAsync ( )
51
- {
52
- return await Task . Run ( ( ) =>
53
- {
54
- var xGitHubEvent = Context . Request . Headers [ "X-GitHub-Event" ] ;
55
- var xGitHubDelivery = Context . Request . Headers [ "X-GitHub-Delivery" ] ;
56
- var xHubSignature = Context . Request . Headers [ "X-Hub-Signature" ] ;
57
- var xHubSignature256 = Context . Request . Headers [ "X-Hub-Signature-256" ] ;
58
-
59
- if ( ! xGitHubEvent . Contains ( "push" ) )
60
- {
61
- // only authenticate push events
62
- return AuthenticateResult . NoResult ( ) ;
63
- }
64
-
65
- if ( ! Guid . TryParse ( xGitHubDelivery . SingleOrDefault ( ) , out _ ) )
66
- {
67
- // delivery should parse as a GUID
68
- return AuthenticateResult . NoResult ( ) ;
69
- }
70
-
71
- if ( ! xHubSignature . Any ( ) )
72
- {
73
- // signature header should be present
74
- return AuthenticateResult . NoResult ( ) ;
75
- }
76
-
77
- var signature = xHubSignature256 . SingleOrDefault ( ) ;
78
-
79
- using var reader = new StreamReader ( Context . Request . Body ) ;
80
- var payload = reader . ReadToEndAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
81
-
82
- if ( ! IsValidSignature ( signature , payload ) )
83
- {
84
- // encrypted signature must be present
85
- return AuthenticateResult . NoResult ( ) ;
86
- }
87
-
88
- var identity = new ClaimsIdentity ( "webhook" , ClaimTypes . Name , ClaimTypes . Role ) ;
89
- identity . AddClaim ( new Claim ( ClaimTypes . Name , "rubberduck-vba-releasebot" ) ) ;
90
- identity . AddClaim ( new Claim ( ClaimTypes . Role , "rubberduck-webhook" ) ) ;
91
- identity . AddClaim ( new Claim ( ClaimTypes . Authentication , "webhook-signature" ) ) ;
92
-
93
- var principal = new ClaimsPrincipal ( identity ) ;
94
- return AuthenticateResult . Success ( new AuthenticationTicket ( principal , "webhook-signature" ) ) ;
95
- } ) ;
96
- }
97
-
98
- private bool IsValidSignature ( string ? signature , string payload )
99
- {
100
- if ( string . IsNullOrWhiteSpace ( signature ) )
101
- {
102
- return false ;
103
- }
104
-
105
- using var sha256 = SHA256 . Create ( ) ;
106
-
107
- var secret = _configuration . GitHubOptions . Value . WebhookToken ;
108
- var bytes = Encoding . UTF8 . GetBytes ( secret + payload ) ;
109
- var check = $ "sha256={ Encoding . UTF8 . GetString ( sha256 . ComputeHash ( bytes ) ) } ";
110
-
111
- return check == payload ;
112
- }
113
- }
0 commit comments