Skip to content

Commit 3c99d35

Browse files
committed
added switch of logic if the pkce fails
1 parent 968ddd5 commit 3c99d35

File tree

1 file changed

+60
-59
lines changed

1 file changed

+60
-59
lines changed

launcher-csharp/Startup.cs

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ namespace DocuSign.CodeExamples
1111
using System.Net.Http;
1212
using System.Net.Http.Headers;
1313
using System.Security.Claims;
14+
using System.Security.Cryptography;
15+
using System.Text;
1416
using System.Text.Json;
1517
using System.Text.RegularExpressions;
1618
using System.Threading.Tasks;
1719
using System.Web;
20+
using Azure.Core;
1821
using DocuSign.CodeExamples.Common;
1922
using DocuSign.CodeExamples.Models;
2023
using DocuSign.Rooms.Api;
@@ -158,54 +161,79 @@ public void ConfigureServices(IServiceCollection services)
158161
options.TokenEndpoint = this.Configuration["DocuSign:TokenEndpoint"];
159162
options.UserInformationEndpoint = this.Configuration["DocuSign:UserInformationEndpoint"];
160163

161-
string codeVerifier = GenerateCodeVerifier();
162-
string codeChallenge = GenerateCodeChallenge(codeVerifier);
164+
foreach (var apiType in this.apiTypes)
165+
{
166+
foreach (var scope in apiType.Value)
167+
{
168+
if (!options.Scope.Contains(scope.ToLower()))
169+
{
170+
options.Scope.Add(scope);
171+
}
172+
}
173+
}
174+
175+
options.SaveTokens = true;
176+
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
177+
options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
178+
options.ClaimActions.MapJsonKey("accounts", "accounts");
179+
options.ClaimActions.MapCustomJson("account_id", obj => this.ExtractDefaultAccountValue(obj, "account_id"));
180+
options.ClaimActions.MapCustomJson("account_name", obj => this.ExtractDefaultAccountValue(obj, "account_name"));
181+
options.ClaimActions.MapCustomJson("base_uri", obj => this.ExtractDefaultAccountValue(obj, "base_uri"));
182+
options.ClaimActions.MapJsonKey("access_token", "access_token");
183+
options.ClaimActions.MapJsonKey("refresh_token", "refresh_token");
184+
options.ClaimActions.MapJsonKey("expires_in", "expires_in");
163185

164186
options.Events = new OAuthEvents
165187
{
166188
OnRedirectToAuthorizationEndpoint = redirectContext =>
167189
{
168190
List<string> scopesForCurrentApi = this.apiTypes.GetValueOrDefault(Enum.Parse<ExamplesApiType>(this.Configuration["API"]));
191+
redirectContext.RedirectUri = this.UpdateRedirectUriScopes(redirectContext.RedirectUri, scopesForCurrentApi);
169192

170-
var redirectUri = this.UpdateRedirectUriScopes(redirectContext.RedirectUri, scopesForCurrentApi);
171-
172-
var pkceQuery = $"&code_challenge={codeChallenge}&code_challenge_method=S256";
173-
redirectContext.RedirectUri = redirectUri + pkceQuery;
174-
175-
redirectContext.HttpContext.Session.SetString("code_verifier", codeVerifier);
193+
redirectContext.Options.UsePkce = this.Configuration["PkceFailed"] == null;
176194

195+
this.Configuration["RedirectUrl"] = redirectContext.RedirectUri;
177196
redirectContext.HttpContext.Response.Redirect(redirectContext.RedirectUri);
178197
return Task.FromResult(0);
179198
},
180199
OnCreatingTicket = async context =>
181200
{
182-
string codeVerifier = context.HttpContext.Session.GetString("code_verifier");
183-
184-
var tokenRequestParams = new Dictionary<string, string>
185-
{
186-
{ "grant_type", "authorization_code" },
187-
{ "code", context.ProtocolMessage.Code },
188-
{ "redirect_uri", context.Properties.RedirectUri },
189-
{ "client_id", options.ClientId },
190-
{ "code_verifier", codeVerifier },
191-
};
192-
193-
var requestContent = new FormUrlEncodedContent(tokenRequestParams);
194-
var requestMessage = new HttpRequestMessage(HttpMethod.Post, options.TokenEndpoint)
195-
{
196-
Content = requestContent
197-
};
198-
var response = await context.Backchannel.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
201+
var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
202+
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
203+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
204+
var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
199205
response.EnsureSuccessStatusCode();
200-
201-
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
202-
context.RunClaimActions(payload.RootElement);
206+
var user = JObject.Parse(await response.Content.ReadAsStringAsync());
207+
user.Add("access_token", context.AccessToken);
208+
user.Add("refresh_token", context.RefreshToken);
209+
user.Add("expires_in", DateTime.Now.Add(context.ExpiresIn.Value).ToString());
210+
using (JsonDocument payload = JsonDocument.Parse(user.ToString()))
211+
{
212+
context.RunClaimActions(payload.RootElement);
213+
}
203214
},
204-
OnRemoteFailure = context =>
215+
OnRemoteFailure = async context =>
205216
{
206-
context.HandleResponse();
207-
context.Response.Redirect("/Home/Error?message=" + context.Failure?.Message);
208-
return Task.FromResult(0);
217+
if (this.Configuration["PkceFailed"] != null)
218+
{
219+
context.HandleResponse();
220+
context.Response.Redirect("/Home/Error?message=" + context.Failure?.Message);
221+
}
222+
else
223+
{
224+
var redirectContext = new RedirectContext<OAuthOptions>(
225+
context.HttpContext,
226+
context.Scheme,
227+
options,
228+
context.Properties,
229+
this.Configuration["RedirectUrl"]);
230+
231+
this.Configuration["PkceFailed"] = "true";
232+
233+
await options.Events.OnRedirectToAuthorizationEndpoint(redirectContext);
234+
235+
context.HandleResponse();
236+
}
209237
},
210238
};
211239
});
@@ -261,33 +289,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
261289
});
262290
}
263291

264-
private string GenerateCodeVerifier()
265-
{
266-
using (var rng = new RNGCryptoServiceProvider())
267-
{
268-
var bytes = new byte[32];
269-
rng.GetBytes(bytes);
270-
return Base64UrlEncode(bytes);
271-
}
272-
}
273-
274-
private string GenerateCodeChallenge(string codeVerifier)
275-
{
276-
using (var sha256 = SHA256.Create())
277-
{
278-
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
279-
return Base64UrlEncode(hash);
280-
}
281-
}
282-
283-
private string Base64UrlEncode(byte[] input)
284-
{
285-
return Convert.ToBase64String(input)
286-
.Replace("+", "-")
287-
.Replace("/", "_")
288-
.Replace("=", "");
289-
}
290-
291292
private string UpdateRedirectUriScopes(string uri, List<string> wantedScopes)
292293
{
293294
const string pattern = @"(?:&|\?)scope=([^&]+)";

0 commit comments

Comments
 (0)