Skip to content

Commit 96eac7e

Browse files
Add support for Dropbox token_access_type parameter (#579)
* Add support for Dropbox response_type and token_access_type params * Follow comment standards in src/AspNet.Security.OAuth.Dropbox/DropboxAuthenticationOptions.cs Co-authored-by: Martin Costello <[email protected]> * Add Dropbox readme with example and optional parameter documentation * Fix casing on options comment * Remove ResponseType option * Add token_access_type tests * Ignore case in string comparison of test Co-authored-by: Martin Costello <[email protected]> Co-authored-by: Martin Costello <[email protected]>
1 parent a46c617 commit 96eac7e

File tree

6 files changed

+124
-2
lines changed

6 files changed

+124
-2
lines changed

AspNet.Security.OAuth.Providers.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{C2CA4B38-A
189189
docs\battlenet.md = docs\battlenet.md
190190
docs\bitbucket.md = docs\bitbucket.md
191191
docs\discord.md = docs\discord.md
192+
docs\dropbox.md = docs\dropbox.md
192193
docs\eveonline.md = docs\eveonline.md
193194
docs\foursquare.md = docs\foursquare.md
194195
docs\gitee.md = docs\gitee.md

docs/dropbox.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Integrating the Dropbox Provider
2+
3+
## Example
4+
5+
```csharp
6+
services.AddAuthentication(options => /* Auth configuration */)
7+
.AddDropbox(options =>
8+
{
9+
options.ClientId = "my-client-id";
10+
options.ClientSecret = "my-client-secret";
11+
});
12+
```
13+
14+
## Required Additional Settings
15+
16+
_None._
17+
18+
## Optional Settings
19+
20+
| Property Name | Property Type | Description | Default Value |
21+
|:--|:--|:--|:--|
22+
| `AccessType` | `string?` | Sets the _token_access_type_ parameter which defines the token response. Accepted values are `online`, `offline`, `legacy` | `null` |
23+
24+
### AccessType
25+
26+
* `online` The response will contain only a short-lived _access_token_.
27+
28+
* `offline` The response will contain a short-lived _access_token_ and a long-lived _refresh_token_ that can be used to request a new short-lived access token as long as a user's approval remains valid.
29+
30+
* `legacy` The response will default to returning a long-lived _access_token_ if they are allowed in the app console. If long-lived access tokens are disabled in the app console, this parameter defaults to `online`.

src/AspNet.Security.OAuth.Dropbox/DropboxAuthenticationHandler.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/*
22
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
33
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
44
* for more information concerning the license and the contributors participating to this project.
@@ -13,6 +13,7 @@
1313
using JetBrains.Annotations;
1414
using Microsoft.AspNetCore.Authentication;
1515
using Microsoft.AspNetCore.Authentication.OAuth;
16+
using Microsoft.AspNetCore.WebUtilities;
1617
using Microsoft.Extensions.Logging;
1718
using Microsoft.Extensions.Options;
1819

@@ -29,6 +30,21 @@ public DropboxAuthenticationHandler(
2930
{
3031
}
3132

33+
/// <inheritdoc />
34+
protected override string BuildChallengeUrl(
35+
[NotNull] AuthenticationProperties properties,
36+
[NotNull] string redirectUri)
37+
{
38+
string challengeUrl = base.BuildChallengeUrl(properties, redirectUri);
39+
40+
if (!string.IsNullOrEmpty(Options.AccessType))
41+
{
42+
challengeUrl = QueryHelpers.AddQueryString(challengeUrl, "token_access_type", Options.AccessType);
43+
}
44+
45+
return challengeUrl;
46+
}
47+
3248
protected override async Task<AuthenticationTicket> CreateTicketAsync(
3349
[NotNull] ClaimsIdentity identity,
3450
[NotNull] AuthenticationProperties properties,

src/AspNet.Security.OAuth.Dropbox/DropboxAuthenticationOptions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/*
22
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
33
* See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
44
* for more information concerning the license and the contributors participating to this project.
@@ -15,6 +15,11 @@ namespace AspNet.Security.OAuth.Dropbox
1515
/// </summary>
1616
public class DropboxAuthenticationOptions : OAuthOptions
1717
{
18+
/// <summary>
19+
/// Gets or sets what the response type from Dropbox should be: online, offline or legacy.
20+
/// </summary>
21+
public string? AccessType { get; set; }
22+
1823
public DropboxAuthenticationOptions()
1924
{
2025
ClaimsIssuer = DropboxAuthenticationDefaults.Issuer;

test/AspNet.Security.OAuth.Providers.Tests/Dropbox/DropboxTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
* for more information concerning the license and the contributors participating to this project.
55
*/
66

7+
using System;
78
using System.Security.Claims;
89
using System.Threading.Tasks;
910
using Microsoft.AspNetCore.Authentication;
11+
using Microsoft.AspNetCore.Authentication.OAuth;
1012
using Microsoft.Extensions.DependencyInjection;
13+
using Shouldly;
1114
using Xunit;
1215
using Xunit.Abstractions;
1316

@@ -42,5 +45,71 @@ public async Task Can_Sign_In_Using_Dropbox(string claimType, string claimValue)
4245
// Assert
4346
AssertClaim(claims, claimType, claimValue);
4447
}
48+
49+
[Theory]
50+
[InlineData("offline")]
51+
[InlineData("online")]
52+
[InlineData("legacy")]
53+
public async Task RedirectUri_Contains_Access_Type(string value)
54+
{
55+
bool accessTypeIsSet = false;
56+
57+
void ConfigureServices(IServiceCollection services)
58+
{
59+
services.PostConfigureAll<DropboxAuthenticationOptions>((options) =>
60+
{
61+
options.AccessType = value;
62+
options.Events = new OAuthEvents
63+
{
64+
OnRedirectToAuthorizationEndpoint = ctx =>
65+
{
66+
accessTypeIsSet = ctx.RedirectUri.Contains($"token_access_type={value}", StringComparison.OrdinalIgnoreCase);
67+
ctx.Response.Redirect(ctx.RedirectUri);
68+
return Task.CompletedTask;
69+
}
70+
};
71+
});
72+
}
73+
74+
// Arrange
75+
using var server = CreateTestServer(ConfigureServices);
76+
77+
// Act
78+
var claims = await AuthenticateUserAsync(server);
79+
80+
// Assert
81+
accessTypeIsSet.ShouldBeTrue();
82+
}
83+
84+
[Fact]
85+
public async Task Response_Contains_Refresh_Token()
86+
{
87+
bool refreshTokenIsPresent = false;
88+
89+
void ConfigureServices(IServiceCollection services)
90+
{
91+
services.PostConfigureAll<DropboxAuthenticationOptions>((options) =>
92+
{
93+
options.AccessType = "offline";
94+
options.Events = new OAuthEvents
95+
{
96+
OnCreatingTicket = ctx =>
97+
{
98+
refreshTokenIsPresent = !string.IsNullOrEmpty(ctx.RefreshToken);
99+
return Task.CompletedTask;
100+
}
101+
};
102+
});
103+
}
104+
105+
// Arrange
106+
using var server = CreateTestServer(ConfigureServices);
107+
108+
// Act
109+
var claims = await AuthenticateUserAsync(server);
110+
111+
// Assert
112+
refreshTokenIsPresent.ShouldBeTrue();
113+
}
45114
}
46115
}

test/AspNet.Security.OAuth.Providers.Tests/Dropbox/bundle.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"contentJson": {
1010
"access_token": "ABCDEFG",
1111
"token_type": "bearer",
12+
"refresh_token": "secret-refresh-token",
1213
"account_id": "dbid:AAH4f99T0taONIb-OurWxbNQ6ywGRopQngc",
1314
"uid": "12345"
1415
}

0 commit comments

Comments
 (0)