|
1 | 1 | /*!
|
2 |
| -OAuth 2.0 errors. |
| 2 | +Library errors for OAuth 2.0 and OpenID. |
3 | 3 | */
|
4 | 4 | use std::{error, fmt};
|
5 | 5 |
|
@@ -91,6 +91,8 @@ impl From<&str> for OAuth2ErrorCode {
|
91 | 91 | }
|
92 | 92 | }
|
93 | 93 | }
|
| 94 | + |
| 95 | +/// Client side error. |
94 | 96 | #[derive(Debug)]
|
95 | 97 | pub enum ClientError {
|
96 | 98 | /// IO error.
|
@@ -165,118 +167,213 @@ use thiserror::Error;
|
165 | 167 | #[cfg(feature = "uma2")]
|
166 | 168 | use crate::uma2::Uma2Error;
|
167 | 169 |
|
| 170 | +/// openid library error. |
| 171 | +/// |
| 172 | +/// Wraps different sources of errors under one error type for library. |
168 | 173 | #[derive(Debug, Error)]
|
169 | 174 | pub enum Error {
|
| 175 | + /// [biscuit] errors. |
170 | 176 | #[error(transparent)]
|
171 | 177 | Jose(#[from] Jose),
|
| 178 | + /// [reqwest] errors. |
172 | 179 | #[error(transparent)]
|
173 | 180 | Http(#[from] Http),
|
| 181 | + /// [serde_json] errors. |
174 | 182 | #[error(transparent)]
|
175 | 183 | Json(#[from] Json),
|
| 184 | + /// Decode token error. |
176 | 185 | #[error(transparent)]
|
177 | 186 | Decode(#[from] Decode),
|
| 187 | + /// Validation error. |
178 | 188 | #[error(transparent)]
|
179 | 189 | Validation(#[from] Validation),
|
| 190 | + /// Errors related to userinfo endpoint. |
180 | 191 | #[error(transparent)]
|
181 | 192 | Userinfo(#[from] Userinfo),
|
| 193 | + /// Errors related to introspection endpoint. |
182 | 194 | #[error(transparent)]
|
183 | 195 | Introspection(#[from] Introspection),
|
| 196 | + /// Secure connection is required. |
184 | 197 | #[error("Url must use TLS: '{0}'")]
|
185 | 198 | Insecure(::reqwest::Url),
|
| 199 | + /// The scope must contain `openid`. |
186 | 200 | #[error("Scope must contain Openid")]
|
187 | 201 | MissingOpenidScope,
|
| 202 | + /// Path segments in url is cannot-be-a-base. |
188 | 203 | #[error("Url: Path segments is cannot-be-a-base")]
|
189 | 204 | CannotBeABase,
|
| 205 | + /// Client side error. |
190 | 206 | #[error(transparent)]
|
191 | 207 | ClientError(#[from] ClientError),
|
192 | 208 | }
|
193 | 209 |
|
| 210 | +/// Decode token error. |
194 | 211 | #[derive(Debug, Error)]
|
195 | 212 | pub enum Decode {
|
196 |
| - #[error("Token Missing a Key Id when the key set has multiple keys")] |
| 213 | + /// Token missing a key id when the key set has multiple keys. |
| 214 | + #[error("Token missing a key id when the key set has multiple keys")] |
197 | 215 | MissingKid,
|
| 216 | + /// Token wants this key id not in the key set. |
198 | 217 | #[error("Token wants this key id not in the key set: {0}")]
|
199 | 218 | MissingKey(String),
|
| 219 | + /// JWK Set is empty. |
200 | 220 | #[error("JWK Set is empty")]
|
201 | 221 | EmptySet,
|
| 222 | + /// No support for EC keys yet. |
202 | 223 | #[error("No support for EC keys yet")]
|
203 | 224 | UnsupportedEllipticCurve,
|
| 225 | + /// No support for Octet key pair yet. |
204 | 226 | #[error("No support for Octet key pair yet")]
|
205 | 227 | UnsupportedOctetKeyPair,
|
206 | 228 | }
|
207 | 229 |
|
| 230 | +/// Validation failure related to mismatch of values, missing values or expired |
| 231 | +/// values. |
208 | 232 | #[derive(Debug, Error)]
|
209 | 233 | pub enum Validation {
|
| 234 | + /// Mismatch in token attribute. |
210 | 235 | #[error(transparent)]
|
211 | 236 | Mismatch(#[from] Mismatch),
|
| 237 | + /// Missing required token attribute. |
212 | 238 | #[error(transparent)]
|
213 | 239 | Missing(#[from] Missing),
|
| 240 | + /// Token expired. |
214 | 241 | #[error(transparent)]
|
215 | 242 | Expired(#[from] Expiry),
|
216 | 243 | }
|
217 | 244 |
|
| 245 | +/// Mismatch in token attribute. |
218 | 246 | #[derive(Debug, Error)]
|
219 | 247 | pub enum Mismatch {
|
| 248 | + /// Client ID and Token authorized party mismatch. |
220 | 249 | #[error("Client ID and Token authorized party mismatch: '{expected}', '{actual}'")]
|
221 |
| - AuthorizedParty { expected: String, actual: String }, |
| 250 | + AuthorizedParty { |
| 251 | + /// Expected value. |
| 252 | + expected: String, |
| 253 | + /// Actual value. |
| 254 | + actual: String, |
| 255 | + }, |
| 256 | + /// Configured issuer and token issuer mismatch. |
222 | 257 | #[error("Configured issuer and token issuer mismatch: '{expected}', '{actual}'")]
|
223 |
| - Issuer { expected: String, actual: String }, |
| 258 | + Issuer { |
| 259 | + /// Expected value. |
| 260 | + expected: String, |
| 261 | + /// Actual value. |
| 262 | + actual: String, |
| 263 | + }, |
| 264 | + /// Given nonce does not match token nonce. |
224 | 265 | #[error("Given nonce does not match token nonce: '{expected}', '{actual}'")]
|
225 |
| - Nonce { expected: String, actual: String }, |
| 266 | + Nonce { |
| 267 | + /// Expected value. |
| 268 | + expected: String, |
| 269 | + /// Actual value. |
| 270 | + actual: String, |
| 271 | + }, |
226 | 272 | }
|
227 | 273 |
|
228 |
| -#[derive(Debug, Error)] |
| 274 | +/// Missing required token attribute. |
| 275 | +#[derive(Debug, Clone, Copy, Error)] |
229 | 276 | pub enum Missing {
|
| 277 | + /// Token missing Audience. |
230 | 278 | #[error("Token missing Audience")]
|
231 | 279 | Audience,
|
| 280 | + /// Token missing AZP. |
232 | 281 | #[error("Token missing AZP")]
|
233 | 282 | AuthorizedParty,
|
| 283 | + /// Token missing Auth Time. |
234 | 284 | #[error("Token missing Auth Time")]
|
235 | 285 | AuthTime,
|
| 286 | + /// Token missing Nonce. |
236 | 287 | #[error("Token missing Nonce")]
|
237 | 288 | Nonce,
|
238 | 289 | }
|
239 | 290 |
|
240 |
| -#[derive(Debug, Error)] |
| 291 | +/// Token expiration variants. |
| 292 | +#[derive(Debug, Clone, Copy, Error)] |
241 | 293 | pub enum Expiry {
|
| 294 | + /// Token expired. |
242 | 295 | #[error("Token expired at: {0}")]
|
243 | 296 | Expires(::chrono::DateTime<::chrono::Utc>),
|
| 297 | + /// Token is too old. |
244 | 298 | #[error("Token is too old: {0}")]
|
245 | 299 | MaxAge(::chrono::Duration),
|
| 300 | + /// Token exp is not valid UNIX timestamp. |
246 | 301 | #[error("Token exp is not valid UNIX timestamp: {0}")]
|
247 | 302 | NotUnix(i64),
|
248 | 303 | }
|
249 | 304 |
|
| 305 | +/// Errors related to userinfo endpoint. |
250 | 306 | #[derive(Debug, Error)]
|
251 | 307 | pub enum Userinfo {
|
| 308 | + /// Config has no userinfo url. |
252 | 309 | #[error("Config has no userinfo url")]
|
253 | 310 | NoUrl,
|
| 311 | + /// The UserInfo Endpoint MUST return a content-type header to indicate |
| 312 | + /// which format is being returned. |
254 | 313 | #[error("The UserInfo Endpoint MUST return a content-type header to indicate which format is being returned")]
|
255 | 314 | MissingContentType,
|
| 315 | + /// Not parsable content type header. |
256 | 316 | #[error("Not parsable content type header: {content_type}")]
|
257 |
| - ParseContentType { content_type: String }, |
| 317 | + ParseContentType { |
| 318 | + /// Content type header value. |
| 319 | + content_type: String, |
| 320 | + }, |
| 321 | + /// Wrong content type header. |
| 322 | + /// |
| 323 | + /// The following are accepted content types: `application/json`, |
| 324 | + /// `application/jwt`. |
258 | 325 | #[error("Wrong content type header: {content_type}. The following are accepted content types: application/json, application/jwt")]
|
259 |
| - WrongContentType { content_type: String, body: Vec<u8> }, |
| 326 | + WrongContentType { |
| 327 | + /// Content type header value. |
| 328 | + content_type: String, |
| 329 | + /// Request body for analyze. |
| 330 | + body: Vec<u8>, |
| 331 | + }, |
| 332 | + /// Token and Userinfo Subjects mismatch. |
260 | 333 | #[error("Token and Userinfo Subjects mismatch: '{expected}', '{actual}'")]
|
261 |
| - MismatchSubject { expected: String, actual: String }, |
| 334 | + MismatchSubject { |
| 335 | + /// Expected token subject value. |
| 336 | + expected: String, |
| 337 | + /// Actual token subject value. |
| 338 | + actual: String, |
| 339 | + }, |
| 340 | + /// The sub (subject) Claim MUST always be returned in the UserInfo |
| 341 | + /// Response. |
262 | 342 | #[error(transparent)]
|
263 | 343 | MissingSubject(#[from] StandardClaimsSubjectMissing),
|
264 | 344 | }
|
265 | 345 |
|
266 |
| -#[derive(Debug, Error)] |
| 346 | +/// The sub (subject) Claim MUST always be returned in the UserInfo Response. |
| 347 | +#[derive(Debug, Copy, Clone, Error)] |
267 | 348 | #[error("The sub (subject) Claim MUST always be returned in the UserInfo Response")]
|
268 | 349 | pub struct StandardClaimsSubjectMissing;
|
269 | 350 |
|
| 351 | +/// Introspection error details. |
270 | 352 | #[derive(Debug, Error)]
|
271 | 353 | pub enum Introspection {
|
| 354 | + /// Config has no introspection url. |
272 | 355 | #[error("Config has no introspection url")]
|
273 | 356 | NoUrl,
|
| 357 | + /// The Introspection Endpoint MUST return a `content-type` header to |
| 358 | + /// indicate which format is being returned. |
274 | 359 | #[error("The Introspection Endpoint MUST return a content-type header to indicate which format is being returned")]
|
275 | 360 | MissingContentType,
|
| 361 | + /// Not parsable content type header. |
276 | 362 | #[error("Not parsable content type header: {content_type}")]
|
277 |
| - ParseContentType { content_type: String }, |
| 363 | + ParseContentType { |
| 364 | + /// Content type header value. |
| 365 | + content_type: String, |
| 366 | + }, |
| 367 | + /// Wrong content type header. |
| 368 | + /// |
| 369 | + /// The following are accepted content types: `application/json`. |
278 | 370 | #[error("Wrong content type header: {content_type}. The following are accepted content types: application/json")]
|
279 |
| - WrongContentType { content_type: String, body: Vec<u8> }, |
| 371 | + WrongContentType { |
| 372 | + /// Content type header value. |
| 373 | + content_type: String, |
| 374 | + /// Request body for analyze. |
| 375 | + body: Vec<u8>, |
| 376 | + }, |
280 | 377 | }
|
281 | 378 |
|
282 | 379 | #[cfg(test)]
|
|
0 commit comments