Skip to content

Commit 8b062e3

Browse files
Update http authentication docs with new operation level auth and scopes (microsoft#2960)
PR added support for it but we need to update the docs to explain the new feature. --------- Co-authored-by: Brian Terlson <brian.terlson@microsoft.com>
1 parent 628517e commit 8b062e3

File tree

8 files changed

+109
-28
lines changed

8 files changed

+109
-28
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
3+
changeKind: internal
4+
packages:
5+
- "@typespec/http"
6+
- "@typespec/openapi3"
7+
---
8+

cspell.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ words:
7070
- protoc
7171
- pwsh
7272
- regen
73+
- respecify
7374
- rpaas
7475
- rushx
7576
- safeint

docs/libraries/http/authentication.md

+95-23
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,40 @@ title: Authentication
44

55
# Configure Http Authentication
66

7-
Notes:
7+
## Configure
88

9-
- Authentication right now can ONLY be configured at the service level.
9+
Authentication can be configured using the `@useAuth` decorator on a service namespace, sub-namespace, interface or operation.
1010

11-
## Configure
11+
The `@useAuth` decorator takes as input the security to apply for all operations contained in the type. If another `@useAuth` was specified on a parent type the new one will override the value of the parent. [See application hierarchy](#application-hierarchy)
1212

13-
Authentication can be configured using the `@useAuth` decorator on the service namespace. The decorator accept a few options:
13+
The input can be a:
1414

15-
- A security scheme (see options [here](https://github.com/microsoft/typespec/blob/main/packages/http/lib/auth.tsp)). This means this is the security scheme to use to authenticate this service.
15+
- A single security scheme (see options [here](https://github.com/microsoft/typespec/blob/main/packages/http/lib/auth.tsp)).
1616

17-
```typespec
18-
@useAuth(Auth1)
19-
```
17+
```typespec
18+
@useAuth(Auth1)
19+
```
2020

21-
- A tuple of security scheme. This means ALL the different security schemes of the tuple MUST be used together to authenticate this service.
21+
- A tuple of security schemes. This creates a security group and means **all** the security schemes in the group **must** be used together to authenticate this service.
2222

23-
```typespec
24-
// Use BOTH Auth1 or Auth2
25-
@useAuth([Auth1, Auth2])
26-
```
23+
```typespec
24+
// Use BOTH Auth1 or Auth2
25+
@useAuth([Auth1, Auth2])
26+
```
2727

28-
- A union of security scheme. This means EITHER of the security schemes can be used to authenticate this service
28+
- A union of security schemes. This means **one** of the security schemes **must** be used to authenticate this service.
2929

30-
```typespec
31-
// Use EITHER Auth1 or Auth2
32-
@useAuth(Auth1 | Auth2)
33-
```
30+
```typespec
31+
// Use EITHER Auth1 or Auth2
32+
@useAuth(Auth1 | Auth2)
33+
```
3434

35-
- A union of tuple security scheme. This means EITHER of the security groups schemes can be used to authenticate this service
35+
- A union of security schemes and tuples representing security groups. This means **one** of the security groups or security schemes **must** be used to authenticate this service.
3636

37-
```typespec
38-
// Use EITHER (Auth1 AND Auth2) OR Auth3
39-
@useAuth([Auth1, Auth2] | Auth3)
40-
```
37+
```typespec
38+
// Use EITHER (Auth1 AND Auth2) OR Auth3
39+
@useAuth([Auth1, Auth2] | Auth3)
40+
```
4141

4242
## Available security schemes
4343

@@ -111,3 +111,75 @@ OAuth 2.0 is an authorization protocol that gives an API client limited access t
111111
OAuth relies on authentication scenarios called flows, which allow the resource owner (user) to share the protected content from the resource server without sharing their credentials.
112112
For that purpose, an OAuth 2.0 server issues access tokens that the client applications can use to access protected resources on behalf of the resource owner.
113113
For more information about OAuth 2.0, see oauth.net and RFC 6749.
114+
115+
## Application hierarchy
116+
117+
The `@useAuth` decorator can be used on a service namespace, sub-namespace, interface or operation. The security scheme specified will be applied to all operations contained in the type.
118+
A child type with a `@useAuth` will **override** the security scheme of the parent type. If the goal is to append a new scheme, you must re-specify the security schemes on the parent and add the new scheme.
119+
120+
### Examples
121+
122+
All operations of `MyService` will use `BasicAuth` to authenticate
123+
124+
```typespec
125+
@useAuth(BasicAuth)
126+
namespace MyService;
127+
128+
op one(): void;
129+
op two(): void;
130+
```
131+
132+
`one` will use `ApiKey` auth and `two` will use the `Basic` auth.
133+
134+
```typespec
135+
@useAuth(BasicAuth)
136+
namespace MyService;
137+
138+
@useAuth(ApiKeyAuth<ApiKeyLocation.query, "api_key">)
139+
op one(): void; // Use ApiKey only
140+
op two(): void; // Use BasicAuth
141+
```
142+
143+
`one` will use `ApiKey` or `Basic` auth and `two` will use the `Basic` auth.
144+
145+
```typespec
146+
@useAuth(BasicAuth)
147+
namespace MyService;
148+
149+
@useAuth(BasicAuth | ApiKeyAuth<ApiKeyLocation.query, "api_key">)
150+
op one(): void; // Use ApiKey only
151+
op two(): void; // Use BasicAuth
152+
```
153+
154+
## OAuth2 Scopes
155+
156+
The `OAuth2` security scheme can have a list of scopes that must be granted to the OAuth2 token to be able to use the operations the security scheme applies to.
157+
When different operations have different scopes, you will likely want to create a template that allows providing OAuth scopes without having to respecify the other properties of the security scheme:
158+
159+
```tsp
160+
alias MyOAuth2<Scopes extends valueof string[]> = OAuth2Auth<[{
161+
type: OAuth2FlowType.implicit;
162+
authorizationUrl: "https://api.example.com/oauth2/authorize";
163+
refreshUrl: "https://api.example.com/oauth2/refresh";
164+
}], Scopes>;
165+
166+
@useAuth<MyOAuth2<["read"]>>
167+
namespace DemoService;
168+
169+
170+
// Use OAuth2 with the "read" scope
171+
op list(): string[];
172+
173+
// Use OAuth2 with the "read" scope or no authentication at all
174+
@useAuth<MyOAuth2<["read"]> | NoAuth>
175+
op read(): string;
176+
177+
// Use OAuth2 with the "write" scope
178+
@useAuth(MyAuth<["write"]>)
179+
op write(value: string): void;
180+
181+
// Use OAuth2 with the "delete" scope
182+
@useAuth(MyAuth<["delete"]>)
183+
op delete(value: string): void;
184+
185+
```

packages/http/lib/auth.tsp

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ model ApiKeyAuth<Location extends ApiKeyLocation, Name extends string> {
111111
* @template Scopes The list of OAuth2 scopes, which are common for every flow from `Flows`. This list is combined with the scopes defined in specific OAuth2 flows.
112112
*/
113113
@doc("")
114-
model OAuth2Auth<Flows extends OAuth2Flow[], Scopes extends string[] = []> {
114+
model OAuth2Auth<Flows extends OAuth2Flow[], Scopes extends valueof string[] = []> {
115115
@doc("OAuth2 authentication")
116116
type: AuthType.oauth2;
117117

packages/http/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export type HttpVerb = "get" | "put" | "post" | "patch" | "delete" | "head";
1818

1919
/** @deprecated use Authentication */
2020
// eslint-disable-next-line @typescript-eslint/no-unused-vars
21-
type ServiceAuthentication = Authentication;
21+
export type ServiceAuthentication = Authentication;
2222

2323
export interface Authentication {
2424
/**

packages/http/test/http-decorators.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ describe("http: decorators", () => {
780780

781781
it("can specify OAuth2 with scopes, which are default for every flow", async () => {
782782
const { Foo } = (await runner.compile(`
783-
alias MyAuth<T extends string[]> = OAuth2Auth<Flows=[{
783+
alias MyAuth<T extends valueof string[]> = OAuth2Auth<Flows=[{
784784
type: OAuth2FlowType.implicit;
785785
authorizationUrl: "https://api.example.com/oauth2/authorize";
786786
refreshUrl: "https://api.example.com/oauth2/refresh";

packages/openapi3/test/security.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ describe("openapi3: security", () => {
258258
`
259259
namespace Test;
260260
261-
alias MyOauth<T extends string[]> = OAuth2Auth<Flows=[{
261+
alias MyOauth<T extends valueof string[]> = OAuth2Auth<Flows=[{
262262
type: OAuth2FlowType.implicit;
263263
authorizationUrl: "https://api.example.com/oauth2/authorize";
264264
refreshUrl: "https://api.example.com/oauth2/refresh";

packages/samples/specs/authentication/operation-auth.tsp

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ using TypeSpec.Http;
88
@useAuth(BearerAuth | MyAuth<["read", "write"]>)
99
namespace TypeSpec.OperationAuth;
1010

11-
alias MyAuth<Scopes extends string[]> = OAuth2Auth<
11+
alias MyAuth<Scopes extends valueof string[]> = OAuth2Auth<
1212
Flows = [
1313
{
1414
type: OAuth2FlowType.implicit;

0 commit comments

Comments
 (0)