Coverage for tests / test_security_oauth2_authorization_code_bearer_scopes_openapi.py: 100%

51 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-12 18:15 +0000

1# Ref: https://github.com/fastapi/fastapi/issues/14454 

2 

3from typing import Annotated, Optional 1abcd

4 

5from fastapi import APIRouter, Depends, FastAPI, Security 1abcd

6from fastapi.security import OAuth2AuthorizationCodeBearer 1abcd

7from fastapi.testclient import TestClient 1abcd

8from inline_snapshot import snapshot 1abcd

9 

10oauth2_scheme = OAuth2AuthorizationCodeBearer( 1abcd

11 authorizationUrl="authorize", 

12 tokenUrl="token", 

13 auto_error=True, 

14 scopes={"read": "Read access", "write": "Write access"}, 

15) 

16 

17 

18async def get_token(token: Annotated[str, Depends(oauth2_scheme)]) -> str: 1abcd

19 return token 1efghijklmnopqrs

20 

21 

22app = FastAPI(dependencies=[Depends(get_token)]) 1abcd

23 

24 

25@app.get("/") 1abcd

26async def root(): 1abcd

27 return {"message": "Hello World"} 1ins

28 

29 

30@app.get( 1abcd

31 "/with-oauth2-scheme", 

32 dependencies=[Security(oauth2_scheme, scopes=["read", "write"])], 

33) 

34async def read_with_oauth2_scheme(): 1abcd

35 return {"message": "Admin Access"} 1hmr

36 

37 

38@app.get( 1abcd

39 "/with-get-token", dependencies=[Security(get_token, scopes=["read", "write"])] 

40) 

41async def read_with_get_token(): 1abcd

42 return {"message": "Admin Access"} 1glq

43 

44 

45router = APIRouter(dependencies=[Security(oauth2_scheme, scopes=["read"])]) 1abcd

46 

47 

48@router.get("/items/") 1abcd

49async def read_items(token: Optional[str] = Depends(oauth2_scheme)): 1abcd

50 return {"token": token} 1fkp

51 

52 

53@router.post("/items/") 1abcd

54async def create_item( 1abcd

55 token: Optional[str] = Security(oauth2_scheme, scopes=["read", "write"]), 

56): 

57 return {"token": token} 1ejo

58 

59 

60app.include_router(router) 1abcd

61 

62client = TestClient(app) 1abcd

63 

64 

65def test_root(): 1abcd

66 response = client.get("/", headers={"Authorization": "Bearer testtoken"}) 1ins

67 assert response.status_code == 200, response.text 1ins

68 assert response.json() == {"message": "Hello World"} 1ins

69 

70 

71def test_read_with_oauth2_scheme(): 1abcd

72 response = client.get( 1hmr

73 "/with-oauth2-scheme", headers={"Authorization": "Bearer testtoken"} 

74 ) 

75 assert response.status_code == 200, response.text 1hmr

76 assert response.json() == {"message": "Admin Access"} 1hmr

77 

78 

79def test_read_with_get_token(): 1abcd

80 response = client.get( 1glq

81 "/with-get-token", headers={"Authorization": "Bearer testtoken"} 

82 ) 

83 assert response.status_code == 200, response.text 1glq

84 assert response.json() == {"message": "Admin Access"} 1glq

85 

86 

87def test_read_token(): 1abcd

88 response = client.get("/items/", headers={"Authorization": "Bearer testtoken"}) 1fkp

89 assert response.status_code == 200, response.text 1fkp

90 assert response.json() == {"token": "testtoken"} 1fkp

91 

92 

93def test_create_token(): 1abcd

94 response = client.post("/items/", headers={"Authorization": "Bearer testtoken"}) 1ejo

95 assert response.status_code == 200, response.text 1ejo

96 assert response.json() == {"token": "testtoken"} 1ejo

97 

98 

99def test_openapi_schema(): 1abcd

100 response = client.get("/openapi.json") 1tuv

101 assert response.status_code == 200, response.text 1tuv

102 assert response.json() == snapshot( 1tuv

103 { 

104 "openapi": "3.1.0", 

105 "info": {"title": "FastAPI", "version": "0.1.0"}, 

106 "paths": { 

107 "/": { 

108 "get": { 

109 "summary": "Root", 

110 "operationId": "root__get", 

111 "responses": { 

112 "200": { 

113 "description": "Successful Response", 

114 "content": {"application/json": {"schema": {}}}, 

115 } 

116 }, 

117 "security": [{"OAuth2AuthorizationCodeBearer": []}], 

118 } 

119 }, 

120 "/with-oauth2-scheme": { 

121 "get": { 

122 "summary": "Read With Oauth2 Scheme", 

123 "operationId": "read_with_oauth2_scheme_with_oauth2_scheme_get", 

124 "responses": { 

125 "200": { 

126 "description": "Successful Response", 

127 "content": {"application/json": {"schema": {}}}, 

128 } 

129 }, 

130 "security": [ 

131 {"OAuth2AuthorizationCodeBearer": ["read", "write"]} 

132 ], 

133 } 

134 }, 

135 "/with-get-token": { 

136 "get": { 

137 "summary": "Read With Get Token", 

138 "operationId": "read_with_get_token_with_get_token_get", 

139 "responses": { 

140 "200": { 

141 "description": "Successful Response", 

142 "content": {"application/json": {"schema": {}}}, 

143 } 

144 }, 

145 "security": [ 

146 {"OAuth2AuthorizationCodeBearer": ["read", "write"]} 

147 ], 

148 } 

149 }, 

150 "/items/": { 

151 "get": { 

152 "summary": "Read Items", 

153 "operationId": "read_items_items__get", 

154 "responses": { 

155 "200": { 

156 "description": "Successful Response", 

157 "content": {"application/json": {"schema": {}}}, 

158 } 

159 }, 

160 "security": [ 

161 {"OAuth2AuthorizationCodeBearer": ["read"]}, 

162 ], 

163 }, 

164 "post": { 

165 "summary": "Create Item", 

166 "operationId": "create_item_items__post", 

167 "responses": { 

168 "200": { 

169 "description": "Successful Response", 

170 "content": {"application/json": {"schema": {}}}, 

171 } 

172 }, 

173 "security": [ 

174 {"OAuth2AuthorizationCodeBearer": ["read", "write"]}, 

175 ], 

176 }, 

177 }, 

178 }, 

179 "components": { 

180 "securitySchemes": { 

181 "OAuth2AuthorizationCodeBearer": { 

182 "type": "oauth2", 

183 "flows": { 

184 "authorizationCode": { 

185 "scopes": { 

186 "read": "Read access", 

187 "write": "Write access", 

188 }, 

189 "authorizationUrl": "authorize", 

190 "tokenUrl": "token", 

191 } 

192 }, 

193 } 

194 } 

195 }, 

196 } 

197 )