From 49b7d17ea373b42a9d24cbbd239f370951f7402b Mon Sep 17 00:00:00 2001 From: adrianbunea Date: Mon, 14 Jun 2021 17:03:52 +0300 Subject: [PATCH 1/5] Add extra fields to AuthorizationSuccess and AuthenticationSuccess --- src/Internal.elm | 36 +++++++++++---- src/OAuth/AuthorizationCode.elm | 69 +++++++++++++++++++++++++--- src/OAuth/AuthorizationCode/PKCE.elm | 69 +++++++++++++++++++++++++--- src/OAuth/ClientCredentials.elm | 65 ++++++++++++++++++++++---- src/OAuth/Implicit.elm | 47 +++++++++++++++---- src/OAuth/Password.elm | 62 ++++++++++++++++++++++--- src/OAuth/Refresh.elm | 62 ++++++++++++++++++++++--- 7 files changed, 356 insertions(+), 54 deletions(-) diff --git a/src/Internal.elm b/src/Internal.elm index fbfb59d..9c520ca 100644 --- a/src/Internal.elm +++ b/src/Internal.elm @@ -1,4 +1,4 @@ -module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorization, AuthorizationError, RequestParts, ResponseType(..), authenticationErrorDecoder, authenticationSuccessDecoder, authorizationErrorParser, decoderFromJust, decoderFromResult, errorDecoder, errorDescriptionDecoder, errorDescriptionParser, errorParser, errorUriDecoder, errorUriParser, expiresInDecoder, expiresInParser, extractTokenString, lenientScopeDecoder, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, refreshTokenDecoder, responseTypeToString, scopeDecoder, scopeParser, spaceSeparatedListParser, stateParser, tokenDecoder, tokenParser, urlAddList, urlAddMaybe) +module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorization, AuthorizationError, Default, RequestParts, ResponseType(..), authenticationErrorDecoder, authenticationSuccessDecoder, authorizationErrorParser, decoderFromJust, decoderFromResult, defaultDecoder, errorDecoder, errorDescriptionDecoder, errorDescriptionParser, errorParser, errorUriDecoder, errorUriParser, expiresInDecoder, expiresInParser, extractTokenString, lenientScopeDecoder, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, refreshTokenDecoder, responseTypeToString, scopeDecoder, scopeParser, spaceSeparatedListParser, stateParser, tokenDecoder, tokenParser, urlAddList, urlAddMaybe) import Base64.Encode as Base64 import Http as Http @@ -19,15 +19,27 @@ import Url.Parser.Query as Query {-| Json decoder for a response. You may provide a custom response decoder using other decoders from this module, or some of your own craft. -} -authenticationSuccessDecoder : Json.Decoder AuthenticationSuccess -authenticationSuccessDecoder = - Json.map4 AuthenticationSuccess +authenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) +authenticationSuccessDecoder extraFieldsDecoder = + Json.map2 AuthenticationSuccess + defaultFieldsDecoder + extraFieldsDecoder + + +defaultFieldsDecoder : Json.Decoder DefaultFields +defaultFieldsDecoder = + Json.map4 DefaultFields tokenDecoder refreshTokenDecoder expiresInDecoder scopeDecoder +defaultDecoder : Json.Decoder Default +defaultDecoder = + Json.succeed Default + + authenticationErrorDecoder : Json.Decoder e -> Json.Decoder (AuthenticationError e) authenticationErrorDecoder errorCodeDecoder = Json.map3 AuthenticationError @@ -245,13 +257,13 @@ makeAuthorizationUrl responseType { clientId, url, redirectUri, scope, state, co { url | query = Just (baseQuery ++ "&" ++ query) } -makeRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Url -> List Http.Header -> String -> RequestParts msg -makeRequest toMsg url headers body = +makeRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Url -> List Http.Header -> String -> RequestParts msg +makeRequest extraFieldsDecoder toMsg url headers body = { method = "POST" , headers = headers , url = Url.toString url , body = Http.stringBody "application/x-www-form-urlencoded" body - , expect = Http.expectJson toMsg authenticationSuccessDecoder + , expect = Http.expectJson toMsg (authenticationSuccessDecoder extraFieldsDecoder) , timeout = Nothing , tracker = Nothing } @@ -370,7 +382,11 @@ type alias AuthorizationError e = } -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -378,6 +394,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + type alias AuthenticationError e = { error : e , errorDescription : Maybe String diff --git a/src/OAuth/AuthorizationCode.elm b/src/OAuth/AuthorizationCode.elm index dc8a592..82ba2ab 100644 --- a/src/OAuth/AuthorizationCode.elm +++ b/src/OAuth/AuthorizationCode.elm @@ -4,6 +4,7 @@ module OAuth.AuthorizationCode exposing , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder , parseCodeWith, Parsers, defaultParsers, defaultCodeParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser + , customAuthenticationSuccessDecoder, makeCustomTokenRequest ) {-| The authorization code grant type is used to obtain both access @@ -351,7 +352,11 @@ type alias Authentication = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -359,6 +364,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + {-| Describes an OAuth error as a result of a request failure - error (_REQUIRED_): @@ -419,7 +428,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, code, url, redirectUri } = let body = @@ -440,7 +449,37 @@ makeTokenRequest toMsg { credentials, code, url, redirectUri } = Just secret -> Just { clientId = credentials.clientId, secret = secret } in - makeRequest toMsg url headers body + makeRequest defaultDecoder toMsg url headers body + + +{-| Builds the request components required to get a token from client credentials, but also includes a decoder for the extra fields + + let req : Http.Request TokenResponse + req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request + +-} +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, url, redirectUri } = + let + body = + [ Builder.string "grant_type" "authorization_code" + , Builder.string "client_id" credentials.clientId + , Builder.string "redirect_uri" (makeRedirectUri redirectUri) + , Builder.string "code" code + ] + |> Builder.toQuery + |> String.dropLeft 1 + + headers = + makeHeaders <| + case credentials.secret of + Nothing -> + Nothing + + Just secret -> + Just { clientId = credentials.clientId, secret = secret } + in + makeRequest extraFieldsDecoder toMsg url headers body @@ -449,8 +488,7 @@ makeTokenRequest toMsg { credentials, code, url, redirectUri } = -- -{-| Json decoder for a positive response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. +{-| Default Json decoder for a positive response. defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess defaultAuthenticationSuccessDecoder = @@ -461,9 +499,26 @@ from this module, or some of your own craft. scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder AuthenticationSuccess +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder + Internal.authenticationSuccessDecoder defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder {-| Json decoder for an errored response. diff --git a/src/OAuth/AuthorizationCode/PKCE.elm b/src/OAuth/AuthorizationCode/PKCE.elm index a9a5efc..7da3073 100644 --- a/src/OAuth/AuthorizationCode/PKCE.elm +++ b/src/OAuth/AuthorizationCode/PKCE.elm @@ -417,7 +417,11 @@ type alias Authentication = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -425,6 +429,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + {-| A simple type alias to ease readability of type signatures -} type alias AuthorizationCode = @@ -491,7 +499,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, code, codeVerifier, url, redirectUri } = let body = @@ -513,7 +521,38 @@ makeTokenRequest toMsg { credentials, code, codeVerifier, url, redirectUri } = Just secret -> Just { clientId = credentials.clientId, secret = secret } in - makeRequest toMsg url headers body + makeRequest defaultDecoder toMsg url headers body + + +{-| Builds the request components required to get a token from client credentials, but also includes a decoder for the extra fields + + let req : Http.Request TokenResponse + req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request + +-} +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, codeVerifier, url, redirectUri } = + let + body = + [ Builder.string "grant_type" "authorization_code" + , Builder.string "client_id" credentials.clientId + , Builder.string "redirect_uri" (makeRedirectUri redirectUri) + , Builder.string "code" code + , Builder.string "code_verifier" (codeVerifierToString codeVerifier) + ] + |> Builder.toQuery + |> String.dropLeft 1 + + headers = + makeHeaders <| + case credentials.secret of + Nothing -> + Nothing + + Just secret -> + Just { clientId = credentials.clientId, secret = secret } + in + makeRequest extraFieldsDecoder toMsg url headers body @@ -522,8 +561,7 @@ makeTokenRequest toMsg { credentials, code, codeVerifier, url, redirectUri } = -- -{-| Json decoder for a positive response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. +{-| Default Json decoder for a positive response. defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess defaultAuthenticationSuccessDecoder = @@ -534,9 +572,26 @@ from this module, or some of your own craft. scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder AuthenticationSuccess +defaultAuthenticationSuccessDecoder : Json.Decoder (AuthenticationSuccess Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder + Internal.authenticationSuccessDecoder defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder {-| Json decoder for an errored response. diff --git a/src/OAuth/ClientCredentials.elm b/src/OAuth/ClientCredentials.elm index 7c9d70a..1e15392 100644 --- a/src/OAuth/ClientCredentials.elm +++ b/src/OAuth/ClientCredentials.elm @@ -97,7 +97,11 @@ type alias Credentials = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -105,6 +109,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + {-| Describes an OAuth error as a result of a request failure - error (_REQUIRED_): @@ -143,13 +151,13 @@ type alias RequestParts a = } -{-| Builds a the request components required to get a token from client credentials +{-| Builds the request components required to get a token from client credentials let req : Http.Request TokenResponse req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, scope, url } = let body = @@ -165,7 +173,32 @@ makeTokenRequest toMsg { credentials, scope, url } = , secret = credentials.secret } in - makeRequest toMsg url headers body + makeRequest defaultDecoder toMsg url headers body + + +{-| Builds the request components required to get a token from client credentials, but also includes a decoder for the extra fields + + let req : Http.Request TokenResponse + req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request + +-} +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, url } = + let + body = + [ Builder.string "grant_type" "client_credentials" ] + |> urlAddList "scope" scope + |> Builder.toQuery + |> String.dropLeft 1 + + headers = + makeHeaders <| + Just + { clientId = credentials.clientId + , secret = credentials.secret + } + in + makeRequest extraFieldsDecoder toMsg url headers body @@ -174,8 +207,7 @@ makeTokenRequest toMsg { credentials, scope, url } = -- -{-| Json decoder for a positive response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. +{-| Default Json decoder for a positive response. defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess defaultAuthenticationSuccessDecoder = @@ -186,9 +218,26 @@ from this module, or some of your own craft. scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder AuthenticationSuccess +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder + Internal.authenticationSuccessDecoder Internal.defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder {-| Json decoder for an errored response. diff --git a/src/OAuth/Implicit.elm b/src/OAuth/Implicit.elm index b967e09..74509c7 100644 --- a/src/OAuth/Implicit.elm +++ b/src/OAuth/Implicit.elm @@ -1,6 +1,7 @@ module OAuth.Implicit exposing ( makeAuthorizationUrl, parseToken, Authorization, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError , parseTokenWith, Parsers, defaultParsers, defaultTokenParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser + , customAuthorizationSuccessParser ) {-| The implicit grant type is used to obtain access tokens (it does not @@ -137,7 +138,11 @@ type alias AuthorizationError = The exact value received from the client -} -type alias AuthorizationSuccess = +type AuthorizationSuccess extraFields + = AuthorizationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -146,6 +151,10 @@ type alias AuthorizationSuccess = } +type Default + = Default + + {-| Describes errors coming from attempting to parse a url after an OAuth redirection - Empty: means there were nothing (related to OAuth 2.0) to parse @@ -153,10 +162,10 @@ type alias AuthorizationSuccess = - Success: a successfully parsed token and response -} -type AuthorizationResult +type AuthorizationResult extraFields = Empty | Error AuthorizationError - | Success AuthorizationSuccess + | Success (AuthorizationSuccess extraFields) {-| Redirects the resource owner (user) to the resource provider server using the specified @@ -181,7 +190,7 @@ authorization server after redirecting the resource owner (user). Returns `ParseResult Empty` when there's nothing or an invalid Url is passed -} -parseToken : Url -> AuthorizationResult +parseToken : Url -> AuthorizationResult Default parseToken = parseTokenWith defaultParsers @@ -198,7 +207,7 @@ This is especially useful when interacting with authorization servers that don't implement the OAuth2.0 specifications. -} -parseTokenWith : Parsers -> Url -> AuthorizationResult +parseTokenWith : Parsers extraFields -> Url -> AuthorizationResult extraFields parseTokenWith { tokenParser, errorParser, authorizationSuccessParser, authorizationErrorParser } url_ = let url = @@ -229,17 +238,17 @@ parseTokenWith { tokenParser, errorParser, authorizationSuccessParser, authoriza - authorizationErrorParser: Selected when the `errorParser` succeeded to parse the remaining parts -} -type alias Parsers = +type alias Parsers extraFields = { tokenParser : Query.Parser (Maybe Token) , errorParser : Query.Parser (Maybe ErrorCode) - , authorizationSuccessParser : Token -> Query.Parser AuthorizationSuccess + , authorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess extraFields) , authorizationErrorParser : ErrorCode -> Query.Parser AuthorizationError } {-| Default parsers according to RFC-6749 -} -defaultParsers : Parsers +defaultParsers : Parsers Default defaultParsers = { tokenParser = defaultTokenParser , errorParser = defaultErrorParser @@ -264,9 +273,27 @@ defaultErrorParser = {-| Default response success parser according to RFC-6749 -} -defaultAuthorizationSuccessParser : Token -> Query.Parser AuthorizationSuccess +defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess Default) defaultAuthorizationSuccessParser accessToken = - Query.map3 (AuthorizationSuccess accessToken Nothing) + Query.map AuthorizationSuccess + (defaultFieldsParser accessToken) + |> Query.map (\authorizationSuccess -> authorizationSuccess Default) + + +{-| Custom response success parser +-} +customAuthorizationSuccessParser : Query.Parser extraFields -> Token -> Query.Parser (AuthorizationSuccess extraFields) +customAuthorizationSuccessParser extraFieldsParser accessToken = + Query.map2 AuthorizationSuccess + (defaultFieldsParser accessToken) + extraFieldsParser + + +{-| Default fields parser +-} +defaultFieldsParser : Token -> Query.Parser DefaultFields +defaultFieldsParser accessToken = + Query.map3 (DefaultFields accessToken Nothing) expiresInParser scopeParser stateParser diff --git a/src/OAuth/Password.elm b/src/OAuth/Password.elm index 4174d63..5f7844b 100644 --- a/src/OAuth/Password.elm +++ b/src/OAuth/Password.elm @@ -103,7 +103,11 @@ type alias Credentials = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -111,6 +115,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + {-| Describes an OAuth error as a result of a request failure - error (_REQUIRED_): @@ -155,7 +163,7 @@ type alias RequestParts a = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, password, scope, url, username } = let body = @@ -170,7 +178,31 @@ makeTokenRequest toMsg { credentials, password, scope, url, username } = headers = makeHeaders credentials in - makeRequest toMsg url headers body + makeRequest defaultDecoder toMsg url headers body + + +{-| Builds the request components required to get a token from client credentials, but also includes a decoder for the extra fields + + let req : Http.Request TokenResponse + req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request + +-} +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, password, scope, url, username } = + let + body = + [ Builder.string "grant_type" "password" + , Builder.string "username" username + , Builder.string "password" password + ] + |> urlAddList "scope" scope + |> Builder.toQuery + |> String.dropLeft 1 + + headers = + makeHeaders credentials + in + makeRequest extraFieldsDecoder toMsg url headers body @@ -179,8 +211,7 @@ makeTokenRequest toMsg { credentials, password, scope, url, username } = -- -{-| Json decoder for a positive response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. +{-| Default Json decoder for a positive response. defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess defaultAuthenticationSuccessDecoder = @@ -191,9 +222,26 @@ from this module, or some of your own craft. scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder AuthenticationSuccess +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder + Internal.authenticationSuccessDecoder Internal.defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder {-| Json decoder for an errored response. diff --git a/src/OAuth/Refresh.elm b/src/OAuth/Refresh.elm index e280959..1030f94 100644 --- a/src/OAuth/Refresh.elm +++ b/src/OAuth/Refresh.elm @@ -2,6 +2,7 @@ module OAuth.Refresh exposing ( makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + , customAuthenticationSuccessDecoder, makeCustomTokenRequest ) {-| If the authorization server issued a refresh token to the client, the @@ -94,7 +95,11 @@ type alias Credentials = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess = +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields + + +type alias DefaultFields = { token : Token , refreshToken : Maybe Token , expiresIn : Maybe Int @@ -102,6 +107,10 @@ type alias AuthenticationSuccess = } +type Default + = Default + + {-| Describes an OAuth error as a result of a request failure - error (_REQUIRED_): @@ -146,7 +155,7 @@ type alias RequestParts a = req = makeTokenRequest toMsg reqParts |> Http.request -} -makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, scope, token, url } = let body = @@ -160,7 +169,30 @@ makeTokenRequest toMsg { credentials, scope, token, url } = headers = makeHeaders credentials in - makeRequest toMsg url headers body + makeRequest defaultDecoder toMsg url headers body + + +{-| Builds the request components required to get a token from client credentials, but also includes a decoder for the extra fields + + let req : Http.Request TokenResponse + req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request + +-} +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, token, url } = + let + body = + [ Builder.string "grant_type" "refresh_token" + , Builder.string "refresh_token" (extractTokenString token) + ] + |> urlAddList "scope" scope + |> Builder.toQuery + |> String.dropLeft 1 + + headers = + makeHeaders credentials + in + makeRequest extraFieldsDecoder toMsg url headers body @@ -169,8 +201,7 @@ makeTokenRequest toMsg { credentials, scope, token, url } = -- -{-| Json decoder for a positive response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. +{-| Default Json decoder for a positive response. defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess defaultAuthenticationSuccessDecoder = @@ -181,9 +212,26 @@ from this module, or some of your own craft. scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder AuthenticationSuccess +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder + Internal.authenticationSuccessDecoder Internal.defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder {-| Json decoder for an errored response. From 9e485011e507cacfd67970178ab4a748caa8a9da Mon Sep 17 00:00:00 2001 From: adrianbunea Date: Tue, 15 Jun 2021 14:21:06 +0300 Subject: [PATCH 2/5] Refactor --- src/Internal.elm | 16 ++- src/OAuth/AuthorizationCode.elm | 121 +---------------- src/OAuth/AuthorizationCode/PKCE.elm | 55 +------- src/OAuth/ClientCredentials.elm | 194 +-------------------------- src/OAuth/Commons.elm | 172 ++++++++++++++++++++++++ src/OAuth/Implicit.elm | 8 +- src/OAuth/Password.elm | 194 +-------------------------- src/OAuth/Refresh.elm | 194 +-------------------------- 8 files changed, 198 insertions(+), 756 deletions(-) create mode 100644 src/OAuth/Commons.elm diff --git a/src/Internal.elm b/src/Internal.elm index 9c520ca..94976f8 100644 --- a/src/Internal.elm +++ b/src/Internal.elm @@ -1,4 +1,4 @@ -module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorization, AuthorizationError, Default, RequestParts, ResponseType(..), authenticationErrorDecoder, authenticationSuccessDecoder, authorizationErrorParser, decoderFromJust, decoderFromResult, defaultDecoder, errorDecoder, errorDescriptionDecoder, errorDescriptionParser, errorParser, errorUriDecoder, errorUriParser, expiresInDecoder, expiresInParser, extractTokenString, lenientScopeDecoder, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, refreshTokenDecoder, responseTypeToString, scopeDecoder, scopeParser, spaceSeparatedListParser, stateParser, tokenDecoder, tokenParser, urlAddList, urlAddMaybe) +module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorization, AuthorizationError, Default(..), DefaultFields, RequestParts, ResponseType(..), authenticationErrorDecoder, authenticationSuccessDecoder, authorizationErrorParser, decoderFromJust, decoderFromResult, defaultDecoder, defaultFields, errorDecoder, errorDescriptionDecoder, errorDescriptionParser, errorParser, errorUriDecoder, errorUriParser, expiresInDecoder, expiresInParser, extraFields, extractTokenString, lenientScopeDecoder, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, refreshTokenDecoder, responseTypeToString, scopeDecoder, scopeParser, spaceSeparatedListParser, stateParser, tokenDecoder, tokenParser, urlAddList, urlAddMaybe) import Base64.Encode as Base64 import Http as Http @@ -403,3 +403,17 @@ type alias AuthenticationError e = , errorDescription : Maybe String , errorUri : Maybe String } + + + +-- ACCESSORS + + +defaultFields : AuthenticationSuccess extraFields -> DefaultFields +defaultFields (AuthenticationSuccess defaultFields_ _) = + defaultFields_ + + +extraFields : AuthenticationSuccess extraFields -> extraFields +extraFields (AuthenticationSuccess _ extraFields_) = + extraFields_ diff --git a/src/OAuth/AuthorizationCode.elm b/src/OAuth/AuthorizationCode.elm index 82ba2ab..5996700 100644 --- a/src/OAuth/AuthorizationCode.elm +++ b/src/OAuth/AuthorizationCode.elm @@ -1,10 +1,8 @@ module OAuth.AuthorizationCode exposing ( makeAuthorizationUrl, parseCode, Authorization, AuthorizationCode, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError - , makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + , makeTokenRequest, Authentication, Credentials, AuthenticationSuccess , parseCodeWith, Parsers, defaultParsers, defaultCodeParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser - , customAuthenticationSuccessDecoder, makeCustomTokenRequest + , makeCustomTokenRequest ) {-| The authorization code grant type is used to obtain both access @@ -480,118 +478,3 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, url, redire Just { clientId = credentials.clientId, secret = secret } in makeRequest extraFieldsDecoder toMsg url headers body - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.AuthorizationCode.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder diff --git a/src/OAuth/AuthorizationCode/PKCE.elm b/src/OAuth/AuthorizationCode/PKCE.elm index 7da3073..495f8eb 100644 --- a/src/OAuth/AuthorizationCode/PKCE.elm +++ b/src/OAuth/AuthorizationCode/PKCE.elm @@ -1,7 +1,7 @@ module OAuth.AuthorizationCode.PKCE exposing ( CodeVerifier, CodeChallenge, codeVerifierFromBytes, codeVerifierToString, mkCodeChallenge, codeChallengeToString , makeAuthorizationUrl, parseCode, Authorization, AuthorizationCode, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError - , makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts + , makeTokenRequest, Authentication, Credentials, AuthenticationError , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder , parseCodeWith, Parsers, defaultParsers, defaultCodeParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser @@ -398,41 +398,6 @@ type alias Authentication = } -{-| The response obtained as a result of an authentication (implicit or not) - - - token (_REQUIRED_): - The access token issued by the authorization server. - - - refreshToken (_OPTIONAL_): - The refresh token, which can be used to obtain new access tokens using the same authorization - grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). - - - expiresIn (_RECOMMENDED_): - The lifetime in seconds of the access token. For example, the value "3600" denotes that the - access token will expire in one hour from the time the response was generated. If omitted, the - authorization server SHOULD provide the expiration time via other means or document the default - value. - - - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): - The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). - --} -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - {-| A simple type alias to ease readability of type signatures -} type alias AuthorizationCode = @@ -463,20 +428,6 @@ type alias AuthenticationError = } -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - {-| Describes at least a `clientId` and if define, a complete set of credentials with the `secret`. The secret is so-to-speak optional and depends on whether the authorization server you interact with requires a 'Basic' authentication on top of @@ -572,7 +523,7 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, codeVerifie scopeDecoder -} -defaultAuthenticationSuccessDecoder : Json.Decoder (AuthenticationSuccess Default) +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Default) defaultAuthenticationSuccessDecoder = Internal.authenticationSuccessDecoder defaultDecoder @@ -589,7 +540,7 @@ from this module, or some of your own craft. scopeDecoder -} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) customAuthenticationSuccessDecoder extraFieldsDecoder = Internal.authenticationSuccessDecoder extraFieldsDecoder diff --git a/src/OAuth/ClientCredentials.elm b/src/OAuth/ClientCredentials.elm index 1e15392..582f056 100644 --- a/src/OAuth/ClientCredentials.elm +++ b/src/OAuth/ClientCredentials.elm @@ -1,8 +1,4 @@ -module OAuth.ClientCredentials exposing - ( makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder - ) +module OAuth.ClientCredentials exposing (makeTokenRequest, Authentication, Credentials) {-| The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to @@ -78,79 +74,6 @@ type alias Credentials = { clientId : String, secret : String } -{-| The response obtained as a result of an authentication (implicit or not) - - - token (_REQUIRED_): - The access token issued by the authorization server. - - - refreshToken (_OPTIONAL_): - The refresh token, which can be used to obtain new access tokens using the same authorization - grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). - - - expiresIn (_RECOMMENDED_): - The lifetime in seconds of the access token. For example, the value "3600" denotes that the - access token will expire in one hour from the time the response was generated. If omitted, the - authorization server SHOULD provide the expiration time via other means or document the default - value. - - - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): - The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). - --} -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - -{-| Describes an OAuth error as a result of a request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - --} -type alias AuthenticationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - } - - -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - {-| Builds the request components required to get a token from client credentials let req : Http.Request TokenResponse @@ -199,118 +122,3 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, url } = } in makeRequest extraFieldsDecoder toMsg url headers body - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder Internal.defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.ClientCredentials.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder diff --git a/src/OAuth/Commons.elm b/src/OAuth/Commons.elm new file mode 100644 index 0000000..17d1e64 --- /dev/null +++ b/src/OAuth/Commons.elm @@ -0,0 +1,172 @@ +module OAuth.Commons exposing (..) + +import Internal +import Json.Decode as Json +import OAuth exposing (ErrorCode, Token, errorCodeFromString) + + +{-| Parts required to build a request. This record is given to `Http.request` in order +to create a new request and may be adjusted at will. +-} +type alias RequestParts a = + Internal.RequestParts a + + +{-| Describes an OAuth error as a result of an authorization request failure + + - error (_REQUIRED_): + A single ASCII error code. + + - errorDescription (_OPTIONAL_) + Human-readable ASCII text providing additional information, used to assist the client developer in + understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT + include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. + + - errorUri (_OPTIONAL_): + A URI identifying a human-readable web page with information about the error, used to + provide the client developer with additional information about the error. Values for the + `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include + characters outside the set `%x21 / %x23-5B / %x5D-7E`. + + - state (_REQUIRED if `state` was present in the authorization request_): + The exact value received from the client + +-} +type alias AuthorizationError = + Internal.AuthorizationError ErrorCode + + +{-| Placeholder used to mark the use of the default OAuth response as a result of an authorization. +Use this when you have no extra fields to decode from the Authorization Server. +-} +type alias Default = + Internal.Default + + + +-- ACCESSORS + + +defaultFields : Internal.AuthenticationSuccess extraFields -> Internal.DefaultFields +defaultFields authenticationSuccess = + Internal.defaultFields authenticationSuccess + + +extraFields : Internal.AuthenticationSuccess extraFields -> extraFields +extraFields authenticationSuccess = + Internal.extraFields authenticationSuccess + + + +-- +-- Json Decoders +-- + + +{-| Default Json decoder for a positive response. + + defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess + defaultAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) +defaultAuthenticationSuccessDecoder = + Internal.authenticationSuccessDecoder Internal.defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder + + +{-| Json decoder for an errored response. + + case res of + Err (Http.BadStatus { body }) -> + case Json.decodeString OAuth.AuthorizationCode.defaultAuthenticationErrorDecoder body of + Ok { error, errorDescription } -> + doSomething + + _ -> + parserFailed + + _ -> + someOtherError + +-} +defaultAuthenticationErrorDecoder : Json.Decoder (Internal.AuthenticationError ErrorCode) +defaultAuthenticationErrorDecoder = + Internal.authenticationErrorDecoder defaultErrorDecoder + + +{-| Json decoder for an 'expire' timestamp +-} +defaultExpiresInDecoder : Json.Decoder (Maybe Int) +defaultExpiresInDecoder = + Internal.expiresInDecoder + + +{-| Json decoder for a 'scope' +-} +defaultScopeDecoder : Json.Decoder (List String) +defaultScopeDecoder = + Internal.scopeDecoder + + +{-| Json decoder for a 'scope', allowing comma- or space-separated scopes +-} +lenientScopeDecoder : Json.Decoder (List String) +lenientScopeDecoder = + Internal.lenientScopeDecoder + + +{-| Json decoder for an 'access\_token' +-} +defaultTokenDecoder : Json.Decoder Token +defaultTokenDecoder = + Internal.tokenDecoder + + +{-| Json decoder for a 'refresh\_token' +-} +defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) +defaultRefreshTokenDecoder = + Internal.refreshTokenDecoder + + +{-| Json decoder for 'error' field +-} +defaultErrorDecoder : Json.Decoder ErrorCode +defaultErrorDecoder = + Internal.errorDecoder errorCodeFromString + + +{-| Json decoder for 'error\_description' field +-} +defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) +defaultErrorDescriptionDecoder = + Internal.errorDescriptionDecoder + + +{-| Json decoder for 'error\_uri' field +-} +defaultErrorUriDecoder : Json.Decoder (Maybe String) +defaultErrorUriDecoder = + Internal.errorUriDecoder diff --git a/src/OAuth/Implicit.elm b/src/OAuth/Implicit.elm index 74509c7..f9fc886 100644 --- a/src/OAuth/Implicit.elm +++ b/src/OAuth/Implicit.elm @@ -151,10 +151,6 @@ type alias DefaultFields = } -type Default - = Default - - {-| Describes errors coming from attempting to parse a url after an OAuth redirection - Empty: means there were nothing (related to OAuth 2.0) to parse @@ -273,11 +269,11 @@ defaultErrorParser = {-| Default response success parser according to RFC-6749 -} -defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess Default) +defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess Internal.Default) defaultAuthorizationSuccessParser accessToken = Query.map AuthorizationSuccess (defaultFieldsParser accessToken) - |> Query.map (\authorizationSuccess -> authorizationSuccess Default) + |> Query.map (\authorizationSuccess -> authorizationSuccess Internal.Default) {-| Custom response success parser diff --git a/src/OAuth/Password.elm b/src/OAuth/Password.elm index 5f7844b..910cf43 100644 --- a/src/OAuth/Password.elm +++ b/src/OAuth/Password.elm @@ -1,8 +1,4 @@ -module OAuth.Password exposing - ( makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder - ) +module OAuth.Password exposing (makeTokenRequest, Authentication, Credentials) {-| The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the @@ -84,79 +80,6 @@ type alias Credentials = { clientId : String, secret : String } -{-| The response obtained as a result of an authentication: - - - token (_REQUIRED_): - The access token issued by the authorization server. - - - refreshToken (_OPTIONAL_): - The refresh token, which can be used to obtain new access tokens using the same authorization - grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). - - - expiresIn (_RECOMMENDED_): - The lifetime in seconds of the access token. For example, the value "3600" denotes that the - access token will expire in one hour from the time the response was generated. If omitted, the - authorization server SHOULD provide the expiration time via other means or document the default - value. - - - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): - The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). - --} -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - -{-| Describes an OAuth error as a result of a request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - --} -type alias AuthenticationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - } - - -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - {-| Builds the request components required to get a token in exchange of the resource owner (user) credentials let req : Http.Request TokenResponse @@ -203,118 +126,3 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, password, scope, makeHeaders credentials in makeRequest extraFieldsDecoder toMsg url headers body - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder Internal.defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.Password.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder diff --git a/src/OAuth/Refresh.elm b/src/OAuth/Refresh.elm index 1030f94..0bc3070 100644 --- a/src/OAuth/Refresh.elm +++ b/src/OAuth/Refresh.elm @@ -1,8 +1,6 @@ module OAuth.Refresh exposing - ( makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder - , customAuthenticationSuccessDecoder, makeCustomTokenRequest + ( makeTokenRequest, Authentication, Credentials + , makeCustomTokenRequest ) {-| If the authorization server issued a refresh token to the client, the @@ -76,79 +74,6 @@ type alias Credentials = { clientId : String, secret : String } -{-| The response obtained as a result of an authentication (implicit or not) - - - token (_REQUIRED_): - The access token issued by the authorization server. - - - refreshToken (_OPTIONAL_): - The refresh token, which can be used to obtain new access tokens using the same authorization - grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). - - - expiresIn (_RECOMMENDED_): - The lifetime in seconds of the access token. For example, the value "3600" denotes that the - access token will expire in one hour from the time the response was generated. If omitted, the - authorization server SHOULD provide the expiration time via other means or document the default - value. - - - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): - The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). - --} -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - -{-| Describes an OAuth error as a result of a request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - --} -type alias AuthenticationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - } - - -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - {-| Builds the request components required to refresh a token let req : Http.Request TokenResponse @@ -193,118 +118,3 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, token, url makeHeaders credentials in makeRequest extraFieldsDecoder toMsg url headers body - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder Internal.defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.ClientCredentials.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder From 5db9be0c50f0197b20df4a4d71c57a3542bf89e3 Mon Sep 17 00:00:00 2001 From: adrianbunea Date: Wed, 16 Jun 2021 14:21:11 +0300 Subject: [PATCH 3/5] Remove Commons, update Docs --- src/Internal.elm | 1 - src/OAuth.elm | 243 +++++++++++++++++++++++++++ src/OAuth/AuthorizationCode.elm | 125 +------------- src/OAuth/AuthorizationCode/PKCE.elm | 163 +----------------- src/OAuth/ClientCredentials.elm | 13 +- src/OAuth/Commons.elm | 172 ------------------- src/OAuth/Implicit.elm | 65 ++++--- src/OAuth/Password.elm | 15 +- src/OAuth/Refresh.elm | 25 +-- 9 files changed, 294 insertions(+), 528 deletions(-) delete mode 100644 src/OAuth/Commons.elm diff --git a/src/Internal.elm b/src/Internal.elm index 94976f8..24a0cc1 100644 --- a/src/Internal.elm +++ b/src/Internal.elm @@ -3,7 +3,6 @@ module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorizat import Base64.Encode as Base64 import Http as Http import Json.Decode as Json -import OAuth exposing (..) import Url exposing (Protocol(..), Url) import Url.Builder as Builder exposing (QueryParameter) import Url.Parser as Url diff --git a/src/OAuth.elm b/src/OAuth.elm index e12c454..675c0b4 100644 --- a/src/OAuth.elm +++ b/src/OAuth.elm @@ -2,6 +2,10 @@ module OAuth exposing ( Token, useToken, tokenToString, tokenFromString , ErrorCode(..), errorCodeToString, errorCodeFromString , TokenType, TokenString, makeToken, makeRefreshToken + , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder + , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + , AuthenticationError, AuthenticationSuccess, AuthorizationError, Default, DefaultFields, RequestParts + , defaultFields, extraFields ) {-| Utility library to manage client-side OAuth 2.0 authentications @@ -48,10 +52,32 @@ used. @docs TokenType, TokenString, makeToken, makeRefreshToken + +## JSON Decoders + +@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder + + +## JSON Decoders (advanced) + +@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + + +## Authenticate + +@docs AuthenticationError, AuthenticationSuccess, AuthorizationError, Default, DefaultFields, RequestParts + + +## Helpers + +@docs defaultFields, extraFields + -} import Extra.Maybe as Maybe import Http as Http +import Internal +import Json.Decode as Json @@ -263,3 +289,220 @@ errorCodeFromString str = _ -> Custom str + + +{-| Parts required to build a request. This record is given to `Http.request` in order +to create a new request and may be adjusted at will. +-} +type alias RequestParts a = + Internal.RequestParts a + + +{-| Describes an OAuth error as a result of a request failure + + - error (_REQUIRED_): + A single ASCII error code. + + - errorDescription (_OPTIONAL_) + Human-readable ASCII text providing additional information, used to assist the client developer in + understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT + include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. + + - errorUri (_OPTIONAL_): + A URI identifying a human-readable web page with information about the error, used to + provide the client developer with additional information about the error. Values for the + `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include + characters outside the set `%x21 / %x23-5B / %x5D-7E`. + +-} +type alias AuthenticationError = + Internal.AuthenticationError ErrorCode + + +{-| The response obtained as a result of an authentication (implicit or not) + + - token (_REQUIRED_): + The access token issued by the authorization server. + + - refreshToken (_OPTIONAL_): + The refresh token, which can be used to obtain new access tokens using the same authorization + grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). + + - expiresIn (_RECOMMENDED_): + The lifetime in seconds of the access token. For example, the value "3600" denotes that the + access token will expire in one hour from the time the response was generated. If omitted, the + authorization server SHOULD provide the expiration time via other means or document the default + value. + + - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): + The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). + +-} +type alias AuthenticationSuccess extraFields = + Internal.AuthenticationSuccess extraFields + + +type alias DefaultFields = + Internal.DefaultFields + + +{-| Placeholder used to mark the use of the default OAuth response as a result of an authorization. +Use this when you have no extra fields to decode from the Authorization Server. +-} +type alias Default = + Internal.Default + + +{-| Describes an OAuth error as a result of an authorization request failure + + - error (_REQUIRED_): + A single ASCII error code. + + - errorDescription (_OPTIONAL_) + Human-readable ASCII text providing additional information, used to assist the client developer in + understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT + include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. + + - errorUri (_OPTIONAL_): + A URI identifying a human-readable web page with information about the error, used to + provide the client developer with additional information about the error. Values for the + `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include + characters outside the set `%x21 / %x23-5B / %x5D-7E`. + + - state (_REQUIRED if `state` was present in the authorization request_): + The exact value received from the client + +-} +type alias AuthorizationError = + Internal.AuthorizationError ErrorCode + + + +-- +-- Json Decoders +-- + + +{-| Default Json decoder for a positive response. + + defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess + defaultAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +defaultAuthenticationSuccessDecoder : Json.Decoder (AuthenticationSuccess Default) +defaultAuthenticationSuccessDecoder = + Internal.authenticationSuccessDecoder Internal.defaultDecoder + + +{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders +from this module, or some of your own craft. + + customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess + customAuthenticationSuccessDecoder = + D.map4 AuthenticationSuccess + tokenDecoder + refreshTokenDecoder + expiresInDecoder + scopeDecoder + +-} +customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) +customAuthenticationSuccessDecoder extraFieldsDecoder = + Internal.authenticationSuccessDecoder extraFieldsDecoder + + +{-| Json decoder for an errored response. + + case res of + Err (Http.BadStatus { body }) -> + case Json.decodeString OAuth.AuthorizationCode.defaultAuthenticationErrorDecoder body of + Ok { error, errorDescription } -> + doSomething + + _ -> + parserFailed + + _ -> + someOtherError + +-} +defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError +defaultAuthenticationErrorDecoder = + Internal.authenticationErrorDecoder defaultErrorDecoder + + +{-| Json decoder for an 'expire' timestamp +-} +defaultExpiresInDecoder : Json.Decoder (Maybe Int) +defaultExpiresInDecoder = + Internal.expiresInDecoder + + +{-| Json decoder for a 'scope' +-} +defaultScopeDecoder : Json.Decoder (List String) +defaultScopeDecoder = + Internal.scopeDecoder + + +{-| Json decoder for a 'scope', allowing comma- or space-separated scopes +-} +lenientScopeDecoder : Json.Decoder (List String) +lenientScopeDecoder = + Internal.lenientScopeDecoder + + +{-| Json decoder for an 'access\_token' +-} +defaultTokenDecoder : Json.Decoder Token +defaultTokenDecoder = + Internal.tokenDecoder + + +{-| Json decoder for a 'refresh\_token' +-} +defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) +defaultRefreshTokenDecoder = + Internal.refreshTokenDecoder + + +{-| Json decoder for 'error' field +-} +defaultErrorDecoder : Json.Decoder ErrorCode +defaultErrorDecoder = + Internal.errorDecoder errorCodeFromString + + +{-| Json decoder for 'error\_description' field +-} +defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) +defaultErrorDescriptionDecoder = + Internal.errorDescriptionDecoder + + +{-| Json decoder for 'error\_uri' field +-} +defaultErrorUriDecoder : Json.Decoder (Maybe String) +defaultErrorUriDecoder = + Internal.errorUriDecoder + + + +-- +-- Helpers +-- + + +defaultFields : Internal.AuthenticationSuccess extraFields -> DefaultFields +defaultFields authenticationSuccess = + Internal.defaultFields authenticationSuccess + + +extraFields : Internal.AuthenticationSuccess extraFields -> extraFields +extraFields authenticationSuccess = + Internal.extraFields authenticationSuccess diff --git a/src/OAuth/AuthorizationCode.elm b/src/OAuth/AuthorizationCode.elm index 5996700..889d172 100644 --- a/src/OAuth/AuthorizationCode.elm +++ b/src/OAuth/AuthorizationCode.elm @@ -1,6 +1,6 @@ module OAuth.AuthorizationCode exposing - ( makeAuthorizationUrl, parseCode, Authorization, AuthorizationCode, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError - , makeTokenRequest, Authentication, Credentials, AuthenticationSuccess + ( makeAuthorizationUrl, parseCode, Authorization, AuthorizationCode, AuthorizationResult(..), AuthorizationSuccess + , makeTokenRequest, Authentication, Credentials , parseCodeWith, Parsers, defaultParsers, defaultCodeParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser , makeCustomTokenRequest ) @@ -58,17 +58,7 @@ request. ## Authenticate -@docs makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - - -## JSON Decoders - -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - - -## JSON Decoders (advanced) - -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs makeTokenRequest, Authentication, Credentials ## Query Parsers (advanced) @@ -78,9 +68,9 @@ request. -} import Http -import Internal as Internal exposing (..) +import Internal exposing (AuthenticationSuccess, authorizationErrorParser, defaultDecoder, errorParser, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, stateParser) import Json.Decode as Json -import OAuth exposing (ErrorCode, Token, errorCodeFromString) +import OAuth exposing (AuthorizationError, Default, ErrorCode, RequestParts, Token, errorCodeFromString) import Url exposing (Url) import Url.Builder as Builder import Url.Parser as Url exposing (()) @@ -125,34 +115,6 @@ type alias Authorization = } -{-| Describes an OAuth error as a result of an authorization request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - - - state (_REQUIRED if `state` was present in the authorization request_): - The exact value received from the client - --} -type alias AuthorizationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - , state : Maybe String - } - - {-| The response obtained as a result of an authorization - code (_REQUIRED_): @@ -331,79 +293,6 @@ type alias Authentication = } -{-| The response obtained as a result of an authentication (implicit or not) - - - token (_REQUIRED_): - The access token issued by the authorization server. - - - refreshToken (_OPTIONAL_): - The refresh token, which can be used to obtain new access tokens using the same authorization - grant as described in [Section 6](https://tools.ietf.org/html/rfc6749#section-6). - - - expiresIn (_RECOMMENDED_): - The lifetime in seconds of the access token. For example, the value "3600" denotes that the - access token will expire in one hour from the time the response was generated. If omitted, the - authorization server SHOULD provide the expiration time via other means or document the default - value. - - - scope (_OPTIONAL, if identical to the scope requested; otherwise, REQUIRED_): - The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). - --} -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - -{-| Describes an OAuth error as a result of a request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - --} -type alias AuthenticationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - } - - -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - {-| Describes at least a `clientId` and if define, a complete set of credentials with the `secret`. The secret is so-to-speak optional and depends on whether the authorization server you interact with requires a 'Basic' authentication on top of @@ -426,7 +315,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (AuthenticationSuccess Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, code, url, redirectUri } = let body = @@ -456,7 +345,7 @@ makeTokenRequest toMsg { credentials, code, url, redirectUri } = req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request -} -makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, url, redirectUri } = let body = diff --git a/src/OAuth/AuthorizationCode/PKCE.elm b/src/OAuth/AuthorizationCode/PKCE.elm index 495f8eb..c43fb53 100644 --- a/src/OAuth/AuthorizationCode/PKCE.elm +++ b/src/OAuth/AuthorizationCode/PKCE.elm @@ -1,9 +1,7 @@ module OAuth.AuthorizationCode.PKCE exposing ( CodeVerifier, CodeChallenge, codeVerifierFromBytes, codeVerifierToString, mkCodeChallenge, codeChallengeToString , makeAuthorizationUrl, parseCode, Authorization, AuthorizationCode, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError - , makeTokenRequest, Authentication, Credentials, AuthenticationError - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + , makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials , parseCodeWith, Parsers, defaultParsers, defaultCodeParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser ) @@ -46,17 +44,7 @@ of this flow. ## Authenticate -@docs makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - - -## JSON Decoders - -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - - -## JSON Decoders (advanced) - -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials ## Query Parsers (advanced) @@ -68,9 +56,9 @@ of this flow. import Base64.Encode as Base64 import Bytes exposing (Bytes) import Http -import Internal as Internal exposing (..) +import Internal exposing (AuthenticationSuccess, authorizationErrorParser, errorParser, parseUrlQuery, stateParser) import Json.Decode as Json -import OAuth exposing (ErrorCode, Token, errorCodeFromString) +import OAuth exposing (Default, ErrorCode, Token, errorCodeFromString) import SHA256 as SHA256 import Url exposing (Url) import Url.Builder as Builder @@ -404,30 +392,6 @@ type alias AuthorizationCode = String -{-| Describes an OAuth error as a result of a request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - --} -type alias AuthenticationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - } - - {-| Describes at least a `clientId` and if define, a complete set of credentials with the `secret`. The secret is so-to-speak optional and depends on whether the authorization server you interact with requires a 'Basic' authentication on top of @@ -450,7 +414,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (AuthenticationSuccess Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, code, codeVerifier, url, redirectUri } = let body = @@ -481,7 +445,7 @@ makeTokenRequest toMsg { credentials, code, codeVerifier, url, redirectUri } = req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request -} -makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, codeVerifier, url, redirectUri } = let body = @@ -504,118 +468,3 @@ makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, code, codeVerifie Just { clientId = credentials.clientId, secret = secret } in makeRequest extraFieldsDecoder toMsg url headers body - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.AuthorizationCode.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder diff --git a/src/OAuth/ClientCredentials.elm b/src/OAuth/ClientCredentials.elm index 582f056..b67e6cf 100644 --- a/src/OAuth/ClientCredentials.elm +++ b/src/OAuth/ClientCredentials.elm @@ -16,24 +16,13 @@ request. ## Authenticate -@docs makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - - -## JSON Decoders - -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - - -## JSON Decoders (advanced) - -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs makeTokenRequest, Authentication, Credentials -} import Http import Internal as Internal exposing (..) import Json.Decode as Json -import OAuth exposing (ErrorCode(..), Token, errorCodeFromString) import Url exposing (Url) import Url.Builder as Builder diff --git a/src/OAuth/Commons.elm b/src/OAuth/Commons.elm deleted file mode 100644 index 17d1e64..0000000 --- a/src/OAuth/Commons.elm +++ /dev/null @@ -1,172 +0,0 @@ -module OAuth.Commons exposing (..) - -import Internal -import Json.Decode as Json -import OAuth exposing (ErrorCode, Token, errorCodeFromString) - - -{-| Parts required to build a request. This record is given to `Http.request` in order -to create a new request and may be adjusted at will. --} -type alias RequestParts a = - Internal.RequestParts a - - -{-| Describes an OAuth error as a result of an authorization request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - - - state (_REQUIRED if `state` was present in the authorization request_): - The exact value received from the client - --} -type alias AuthorizationError = - Internal.AuthorizationError ErrorCode - - -{-| Placeholder used to mark the use of the default OAuth response as a result of an authorization. -Use this when you have no extra fields to decode from the Authorization Server. --} -type alias Default = - Internal.Default - - - --- ACCESSORS - - -defaultFields : Internal.AuthenticationSuccess extraFields -> Internal.DefaultFields -defaultFields authenticationSuccess = - Internal.defaultFields authenticationSuccess - - -extraFields : Internal.AuthenticationSuccess extraFields -> extraFields -extraFields authenticationSuccess = - Internal.extraFields authenticationSuccess - - - --- --- Json Decoders --- - - -{-| Default Json decoder for a positive response. - - defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess - defaultAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -defaultAuthenticationSuccessDecoder : Json.Decoder (Internal.AuthenticationSuccess Internal.Default) -defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder Internal.defaultDecoder - - -{-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders -from this module, or some of your own craft. - - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - --} -customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (Internal.AuthenticationSuccess extraFields) -customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder - - -{-| Json decoder for an errored response. - - case res of - Err (Http.BadStatus { body }) -> - case Json.decodeString OAuth.AuthorizationCode.defaultAuthenticationErrorDecoder body of - Ok { error, errorDescription } -> - doSomething - - _ -> - parserFailed - - _ -> - someOtherError - --} -defaultAuthenticationErrorDecoder : Json.Decoder (Internal.AuthenticationError ErrorCode) -defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder - - -{-| Json decoder for an 'expire' timestamp --} -defaultExpiresInDecoder : Json.Decoder (Maybe Int) -defaultExpiresInDecoder = - Internal.expiresInDecoder - - -{-| Json decoder for a 'scope' --} -defaultScopeDecoder : Json.Decoder (List String) -defaultScopeDecoder = - Internal.scopeDecoder - - -{-| Json decoder for a 'scope', allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Internal.lenientScopeDecoder - - -{-| Json decoder for an 'access\_token' --} -defaultTokenDecoder : Json.Decoder Token -defaultTokenDecoder = - Internal.tokenDecoder - - -{-| Json decoder for a 'refresh\_token' --} -defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) -defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder - - -{-| Json decoder for 'error' field --} -defaultErrorDecoder : Json.Decoder ErrorCode -defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString - - -{-| Json decoder for 'error\_description' field --} -defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) -defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder - - -{-| Json decoder for 'error\_uri' field --} -defaultErrorUriDecoder : Json.Decoder (Maybe String) -defaultErrorUriDecoder = - Internal.errorUriDecoder diff --git a/src/OAuth/Implicit.elm b/src/OAuth/Implicit.elm index f9fc886..7361eb2 100644 --- a/src/OAuth/Implicit.elm +++ b/src/OAuth/Implicit.elm @@ -1,7 +1,7 @@ module OAuth.Implicit exposing - ( makeAuthorizationUrl, parseToken, Authorization, AuthorizationResult(..), AuthorizationSuccess, AuthorizationError - , parseTokenWith, Parsers, defaultParsers, defaultTokenParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser - , customAuthorizationSuccessParser + ( makeAuthorizationUrl, parseToken, Authorization, AuthorizationResult(..), AuthorizationSuccess + , defaultFields, extraFields + , parseTokenWith, Parsers, defaultParsers, defaultTokenParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser, customAuthorizationSuccessParser ) {-| The implicit grant type is used to obtain access tokens (it does not @@ -34,17 +34,22 @@ request. ## Authorize -@docs makeAuthorizationUrl, parseToken, Authorization, AuthorizationResult, AuthorizationSuccess, AuthorizationError +@docs makeAuthorizationUrl, parseToken, Authorization, AuthorizationResult, AuthorizationSuccess + + +## Helpers + +@docs defaultFields, extraFields ## Custom Parsers (advanced) -@docs parseTokenWith, Parsers, defaultParsers, defaultTokenParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser +@docs parseTokenWith, Parsers, defaultParsers, defaultTokenParser, defaultErrorParser, defaultAuthorizationSuccessParser, defaultAuthorizationErrorParser, customAuthorizationSuccessParser -} -import Internal exposing (..) -import OAuth exposing (ErrorCode(..), Token, errorCodeFromString) +import Internal exposing (authorizationErrorParser, errorParser, expiresInParser, parseUrlQuery, scopeParser, stateParser, tokenParser) +import OAuth exposing (AuthorizationError, Default, ErrorCode(..), Token, errorCodeFromString) import Url exposing (Protocol(..), Url) import Url.Parser as Url exposing (()) import Url.Parser.Query as Query @@ -88,34 +93,6 @@ type alias Authorization = } -{-| Describes an OAuth error as a result of an authorization request failure - - - error (_REQUIRED_): - A single ASCII error code. - - - errorDescription (_OPTIONAL_) - Human-readable ASCII text providing additional information, used to assist the client developer in - understanding the error that occurred. Values for the `errorDescription` parameter MUST NOT - include characters outside the set `%x20-21 / %x23-5B / %x5D-7E`. - - - errorUri (_OPTIONAL_): - A URI identifying a human-readable web page with information about the error, used to - provide the client developer with additional information about the error. Values for the - `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include - characters outside the set `%x21 / %x23-5B / %x5D-7E`. - - - state (_REQUIRED if `state` was present in the authorization request_): - The exact value received from the client - --} -type alias AuthorizationError = - { error : ErrorCode - , errorDescription : Maybe String - , errorUri : Maybe String - , state : Maybe String - } - - {-| The response obtained as a result of an authentication (implicit or not) - token (_REQUIRED_): @@ -192,6 +169,22 @@ parseToken = +-- +-- Helpers +-- + + +defaultFields : AuthorizationSuccess extraFields -> DefaultFields +defaultFields (AuthorizationSuccess defaultFields_ _) = + defaultFields_ + + +extraFields : AuthorizationSuccess extraFields -> extraFields +extraFields (AuthorizationSuccess _ extraFields_) = + extraFields_ + + + -- -- Authorize (Advanced) -- @@ -269,7 +262,7 @@ defaultErrorParser = {-| Default response success parser according to RFC-6749 -} -defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess Internal.Default) +defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess Default) defaultAuthorizationSuccessParser accessToken = Query.map AuthorizationSuccess (defaultFieldsParser accessToken) diff --git a/src/OAuth/Password.elm b/src/OAuth/Password.elm index 910cf43..6972435 100644 --- a/src/OAuth/Password.elm +++ b/src/OAuth/Password.elm @@ -1,4 +1,4 @@ -module OAuth.Password exposing (makeTokenRequest, Authentication, Credentials) +module OAuth.Password exposing (makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials) {-| The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the @@ -17,24 +17,13 @@ request. ## Authenticate -@docs makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - - -## JSON Decoders - -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - - -## JSON Decoders (advanced) - -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials -} import Http import Internal as Internal exposing (..) import Json.Decode as Json -import OAuth exposing (ErrorCode(..), Token, errorCodeFromString) import Url exposing (Url) import Url.Builder as Builder diff --git a/src/OAuth/Refresh.elm b/src/OAuth/Refresh.elm index 0bc3070..74b514c 100644 --- a/src/OAuth/Refresh.elm +++ b/src/OAuth/Refresh.elm @@ -1,7 +1,4 @@ -module OAuth.Refresh exposing - ( makeTokenRequest, Authentication, Credentials - , makeCustomTokenRequest - ) +module OAuth.Refresh exposing (makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials) {-| If the authorization server issued a refresh token to the client, the client may make a refresh request to the token endpoint to obtain a new access token @@ -17,24 +14,14 @@ can be used in subsequent requests. ## Authenticate -@docs makeTokenRequest, Authentication, Credentials, AuthenticationSuccess, AuthenticationError, RequestParts - - -## JSON Decoders - -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - - -## JSON Decoders (advanced) - -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs makeTokenRequest, makeCustomTokenRequest, Authentication, Credentials -} import Http -import Internal as Internal exposing (..) +import Internal exposing (AuthenticationSuccess, defaultDecoder, extractTokenString, makeHeaders, makeRequest, urlAddList) import Json.Decode as Json -import OAuth exposing (ErrorCode(..), Token, errorCodeFromString) +import OAuth exposing (Default, ErrorCode(..), RequestParts, Token) import Url exposing (Url) import Url.Builder as Builder @@ -80,7 +67,7 @@ type alias Credentials = req = makeTokenRequest toMsg reqParts |> Http.request -} -makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (AuthenticationSuccess Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, scope, token, url } = let body = @@ -103,7 +90,7 @@ makeTokenRequest toMsg { credentials, scope, token, url } = req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request -} -makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, token, url } = let body = From b6e35980d7c0e35793fd517577ec7079679343d4 Mon Sep 17 00:00:00 2001 From: adrianbunea Date: Wed, 16 Jun 2021 16:08:21 +0300 Subject: [PATCH 4/5] Fix cyclic import --- src/Internal.elm | 183 +-------------------------- src/OAuth.elm | 170 ++++++++++++++++++------- src/OAuth/AuthorizationCode.elm | 4 +- src/OAuth/AuthorizationCode/PKCE.elm | 4 +- src/OAuth/ClientCredentials.elm | 7 +- src/OAuth/Implicit.elm | 2 +- src/OAuth/Password.elm | 7 +- src/OAuth/Refresh.elm | 4 +- 8 files changed, 146 insertions(+), 235 deletions(-) diff --git a/src/Internal.elm b/src/Internal.elm index 24a0cc1..fca11cd 100644 --- a/src/Internal.elm +++ b/src/Internal.elm @@ -1,8 +1,9 @@ -module Internal exposing (AuthenticationError, AuthenticationSuccess, Authorization, AuthorizationError, Default(..), DefaultFields, RequestParts, ResponseType(..), authenticationErrorDecoder, authenticationSuccessDecoder, authorizationErrorParser, decoderFromJust, decoderFromResult, defaultDecoder, defaultFields, errorDecoder, errorDescriptionDecoder, errorDescriptionParser, errorParser, errorUriDecoder, errorUriParser, expiresInDecoder, expiresInParser, extraFields, extractTokenString, lenientScopeDecoder, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, refreshTokenDecoder, responseTypeToString, scopeDecoder, scopeParser, spaceSeparatedListParser, stateParser, tokenDecoder, tokenParser, urlAddList, urlAddMaybe) +module Internal exposing (Authorization, ResponseType(..), authorizationErrorParser, defaultDecoder, errorDescriptionParser, errorParser, errorUriParser, expiresInParser, extractTokenString, makeAuthorizationUrl, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, protocolToString, responseTypeToString, scopeParser, spaceSeparatedListParser, stateParser, tokenParser, urlAddList, urlAddMaybe) import Base64.Encode as Base64 import Http as Http import Json.Decode as Json +import OAuth exposing (AuthenticationError, AuthenticationSuccess, AuthorizationError, Default, DefaultFields, ErrorCode, RequestParts, Token, customAuthenticationSuccessDecoder, makeToken, tokenToString) import Url exposing (Protocol(..), Url) import Url.Builder as Builder exposing (QueryParameter) import Url.Parser as Url @@ -11,129 +12,13 @@ import Url.Parser.Query as Query -- --- Json Decoders +-- Decoders -- -{-| Json decoder for a response. You may provide a custom response decoder using other decoders -from this module, or some of your own craft. --} -authenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) -authenticationSuccessDecoder extraFieldsDecoder = - Json.map2 AuthenticationSuccess - defaultFieldsDecoder - extraFieldsDecoder - - -defaultFieldsDecoder : Json.Decoder DefaultFields -defaultFieldsDecoder = - Json.map4 DefaultFields - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder - - defaultDecoder : Json.Decoder Default defaultDecoder = - Json.succeed Default - - -authenticationErrorDecoder : Json.Decoder e -> Json.Decoder (AuthenticationError e) -authenticationErrorDecoder errorCodeDecoder = - Json.map3 AuthenticationError - errorCodeDecoder - errorDescriptionDecoder - errorUriDecoder - - -{-| Json decoder for an expire timestamp --} -expiresInDecoder : Json.Decoder (Maybe Int) -expiresInDecoder = - Json.maybe <| Json.field "expires_in" Json.int - - -{-| Json decoder for a scope --} -scopeDecoder : Json.Decoder (List String) -scopeDecoder = - Json.map (Maybe.withDefault []) <| Json.maybe <| Json.field "scope" (Json.list Json.string) - - -{-| Json decoder for a scope, allowing comma- or space-separated scopes --} -lenientScopeDecoder : Json.Decoder (List String) -lenientScopeDecoder = - Json.map (Maybe.withDefault []) <| - Json.maybe <| - Json.field "scope" <| - Json.oneOf - [ Json.list Json.string - , Json.map (String.split ",") Json.string - ] - - -{-| Json decoder for an access token --} -tokenDecoder : Json.Decoder Token -tokenDecoder = - Json.andThen (decoderFromJust "missing or invalid 'access_token' / 'token_type'") <| - Json.map2 makeToken - (Json.field "token_type" Json.string |> Json.map Just) - (Json.field "access_token" Json.string |> Json.map Just) - - -{-| Json decoder for a refresh token --} -refreshTokenDecoder : Json.Decoder (Maybe Token) -refreshTokenDecoder = - Json.andThen (decoderFromJust "missing or invalid 'refresh_token' / 'token_type'") <| - Json.map2 makeRefreshToken - (Json.field "token_type" Json.string) - (Json.field "refresh_token" Json.string |> Json.maybe) - - -{-| Json decoder for 'error' field --} -errorDecoder : (String -> a) -> Json.Decoder a -errorDecoder errorCodeFromString = - Json.map errorCodeFromString <| Json.field "error" Json.string - - -{-| Json decoder for 'error\_description' field --} -errorDescriptionDecoder : Json.Decoder (Maybe String) -errorDescriptionDecoder = - Json.maybe <| Json.field "error_description" Json.string - - -{-| Json decoder for 'error\_uri' field --} -errorUriDecoder : Json.Decoder (Maybe String) -errorUriDecoder = - Json.maybe <| Json.field "error_uri" Json.string - - -{-| Combinator for JSON decoders to extract values from a `Maybe` or fail -with the given message (when `Nothing` is encountered) --} -decoderFromJust : String -> Maybe a -> Json.Decoder a -decoderFromJust msg = - Maybe.map Json.succeed >> Maybe.withDefault (Json.fail msg) - - -{-| Combinator for JSON decoders to extact values from a `Result _ _` or fail -with an appropriate message --} -decoderFromResult : Result String a -> Json.Decoder a -decoderFromResult res = - case res of - Err msg -> - Json.fail msg - - Ok a -> - Json.succeed a + Json.succeed OAuth.Default @@ -142,7 +27,7 @@ decoderFromResult res = -- -authorizationErrorParser : e -> Query.Parser (AuthorizationError e) +authorizationErrorParser : ErrorCode -> Query.Parser AuthorizationError authorizationErrorParser errorCode = Query.map3 (AuthorizationError errorCode) errorDescriptionParser @@ -262,7 +147,7 @@ makeRequest extraFieldsDecoder toMsg url headers body = , headers = headers , url = Url.toString url , body = Http.stringBody "application/x-www-form-urlencoded" body - , expect = Http.expectJson toMsg (authenticationSuccessDecoder extraFieldsDecoder) + , expect = Http.expectJson toMsg (customAuthenticationSuccessDecoder extraFieldsDecoder) , timeout = Nothing , tracker = Nothing } @@ -352,17 +237,6 @@ type ResponseType -- -type alias RequestParts a = - { method : String - , headers : List Http.Header - , url : String - , body : Http.Body - , expect : Http.Expect a - , timeout : Maybe Float - , tracker : Maybe String - } - - type alias Authorization = { clientId : String , url : Url @@ -371,48 +245,3 @@ type alias Authorization = , state : Maybe String , codeChallenge : Maybe String } - - -type alias AuthorizationError e = - { error : e - , errorDescription : Maybe String - , errorUri : Maybe String - , state : Maybe String - } - - -type AuthenticationSuccess extraFields - = AuthenticationSuccess DefaultFields extraFields - - -type alias DefaultFields = - { token : Token - , refreshToken : Maybe Token - , expiresIn : Maybe Int - , scope : List String - } - - -type Default - = Default - - -type alias AuthenticationError e = - { error : e - , errorDescription : Maybe String - , errorUri : Maybe String - } - - - --- ACCESSORS - - -defaultFields : AuthenticationSuccess extraFields -> DefaultFields -defaultFields (AuthenticationSuccess defaultFields_ _) = - defaultFields_ - - -extraFields : AuthenticationSuccess extraFields -> extraFields -extraFields (AuthenticationSuccess _ extraFields_) = - extraFields_ diff --git a/src/OAuth.elm b/src/OAuth.elm index 675c0b4..7a385d7 100644 --- a/src/OAuth.elm +++ b/src/OAuth.elm @@ -2,10 +2,11 @@ module OAuth exposing ( Token, useToken, tokenToString, tokenFromString , ErrorCode(..), errorCodeToString, errorCodeFromString , TokenType, TokenString, makeToken, makeRefreshToken - , defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder - , defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder - , AuthenticationError, AuthenticationSuccess, AuthorizationError, Default, DefaultFields, RequestParts + , defaultAuthenticationSuccessDecoder, customAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder + , defaultExpiresInDecoder, defaultScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder + , AuthenticationError, AuthenticationSuccess(..), AuthorizationError, Default(..), DefaultFields, RequestParts , defaultFields, extraFields + , lenientScopeDecoder ) {-| Utility library to manage client-side OAuth 2.0 authentications @@ -55,12 +56,12 @@ used. ## JSON Decoders -@docs defaultAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder +@docs defaultAuthenticationSuccessDecoder, customAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder ## JSON Decoders (advanced) -@docs defaultExpiresInDecoder, defaultScopeDecoder, lenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder +@docs defaultExpiresInDecoder, defaultScopeDecoder, defaultLenientScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder ## Authenticate @@ -76,7 +77,6 @@ used. import Extra.Maybe as Maybe import Http as Http -import Internal import Json.Decode as Json @@ -295,10 +295,17 @@ errorCodeFromString str = to create a new request and may be adjusted at will. -} type alias RequestParts a = - Internal.RequestParts a + { method : String + , headers : List Http.Header + , url : String + , body : Http.Body + , expect : Http.Expect a + , timeout : Maybe Float + , tracker : Maybe String + } -{-| Describes an OAuth error as a result of a request failure +{-| Describes an OAuth error as a result of an authorization request failure - error (_REQUIRED_): A single ASCII error code. @@ -314,9 +321,16 @@ type alias RequestParts a = `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include characters outside the set `%x21 / %x23-5B / %x5D-7E`. + - state (_REQUIRED if `state` was present in the authorization request_): + The exact value received from the client + -} -type alias AuthenticationError = - Internal.AuthenticationError ErrorCode +type alias AuthorizationError = + { error : ErrorCode + , errorDescription : Maybe String + , errorUri : Maybe String + , state : Maybe String + } {-| The response obtained as a result of an authentication (implicit or not) @@ -338,22 +352,26 @@ type alias AuthenticationError = The scope of the access token as described by [Section 3.3](https://tools.ietf.org/html/rfc6749#section-3.3). -} -type alias AuthenticationSuccess extraFields = - Internal.AuthenticationSuccess extraFields +type AuthenticationSuccess extraFields + = AuthenticationSuccess DefaultFields extraFields type alias DefaultFields = - Internal.DefaultFields + { token : Token + , refreshToken : Maybe Token + , expiresIn : Maybe Int + , scope : List String + } {-| Placeholder used to mark the use of the default OAuth response as a result of an authorization. Use this when you have no extra fields to decode from the Authorization Server. -} -type alias Default = - Internal.Default +type Default + = Default -{-| Describes an OAuth error as a result of an authorization request failure +{-| Describes an OAuth error as a result of a request failure - error (_REQUIRED_): A single ASCII error code. @@ -369,12 +387,12 @@ type alias Default = `errorUri` parameter MUST conform to the URI-reference syntax and thus MUST NOT include characters outside the set `%x21 / %x23-5B / %x5D-7E`. - - state (_REQUIRED if `state` was present in the authorization request_): - The exact value received from the client - -} -type alias AuthorizationError = - Internal.AuthorizationError ErrorCode +type alias AuthenticationError = + { error : ErrorCode + , errorDescription : Maybe String + , errorUri : Maybe String + } @@ -396,24 +414,45 @@ type alias AuthorizationError = -} defaultAuthenticationSuccessDecoder : Json.Decoder (AuthenticationSuccess Default) defaultAuthenticationSuccessDecoder = - Internal.authenticationSuccessDecoder Internal.defaultDecoder + authenticationSuccessDecoder defaultDecoder + + +defaultDecoder : Json.Decoder Default +defaultDecoder = + Json.succeed Default {-| Custom Json decoder for a positive response. You provide a custom response decoder for any extra fields using other decoders from this module, or some of your own craft. - customAuthenticationSuccessDecoder : Decoder extraFields -> Decoder AuthenticationSuccess - customAuthenticationSuccessDecoder = - D.map4 AuthenticationSuccess - tokenDecoder - refreshTokenDecoder - expiresInDecoder - scopeDecoder + extraFieldsDecoder : Decoder ExtraFields + extraFieldsDecoder = + D.map4 ExtraFields + defaultTokenDecoder + defaultRefreshTokenDecoder + defaultExpiresInDecoder + defaultScopeDecoder -} customAuthenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) customAuthenticationSuccessDecoder extraFieldsDecoder = - Internal.authenticationSuccessDecoder extraFieldsDecoder + authenticationSuccessDecoder extraFieldsDecoder + + +authenticationSuccessDecoder : Json.Decoder extraFields -> Json.Decoder (AuthenticationSuccess extraFields) +authenticationSuccessDecoder extraFieldsDecoder = + Json.map2 AuthenticationSuccess + defaultFieldsDecoder + extraFieldsDecoder + + +defaultFieldsDecoder : Json.Decoder DefaultFields +defaultFieldsDecoder = + Json.map4 DefaultFields + defaultTokenDecoder + defaultRefreshTokenDecoder + defaultExpiresInDecoder + defaultScopeDecoder {-| Json decoder for an errored response. @@ -433,63 +472,104 @@ customAuthenticationSuccessDecoder extraFieldsDecoder = -} defaultAuthenticationErrorDecoder : Json.Decoder AuthenticationError defaultAuthenticationErrorDecoder = - Internal.authenticationErrorDecoder defaultErrorDecoder + authenticationErrorDecoder defaultErrorDecoder + + +authenticationErrorDecoder : Json.Decoder ErrorCode -> Json.Decoder AuthenticationError +authenticationErrorDecoder errorCodeDecoder = + Json.map3 AuthenticationError + errorCodeDecoder + defaultErrorDescriptionDecoder + defaultErrorUriDecoder {-| Json decoder for an 'expire' timestamp -} defaultExpiresInDecoder : Json.Decoder (Maybe Int) defaultExpiresInDecoder = - Internal.expiresInDecoder + Json.maybe <| Json.field "expires_in" Json.int {-| Json decoder for a 'scope' -} defaultScopeDecoder : Json.Decoder (List String) defaultScopeDecoder = - Internal.scopeDecoder + Json.map (Maybe.withDefault []) <| Json.maybe <| Json.field "scope" (Json.list Json.string) {-| Json decoder for a 'scope', allowing comma- or space-separated scopes -} lenientScopeDecoder : Json.Decoder (List String) lenientScopeDecoder = - Internal.lenientScopeDecoder + Json.map (Maybe.withDefault []) <| + Json.maybe <| + Json.field "scope" <| + Json.oneOf + [ Json.list Json.string + , Json.map (String.split ",") Json.string + ] {-| Json decoder for an 'access\_token' -} defaultTokenDecoder : Json.Decoder Token defaultTokenDecoder = - Internal.tokenDecoder + Json.andThen (decoderFromJust "missing or invalid 'access_token' / 'token_type'") <| + Json.map2 makeToken + (Json.field "token_type" Json.string |> Json.map Just) + (Json.field "access_token" Json.string |> Json.map Just) {-| Json decoder for a 'refresh\_token' -} defaultRefreshTokenDecoder : Json.Decoder (Maybe Token) defaultRefreshTokenDecoder = - Internal.refreshTokenDecoder + Json.andThen (decoderFromJust "missing or invalid 'refresh_token' / 'token_type'") <| + Json.map2 makeRefreshToken + (Json.field "token_type" Json.string) + (Json.field "refresh_token" Json.string |> Json.maybe) {-| Json decoder for 'error' field -} defaultErrorDecoder : Json.Decoder ErrorCode defaultErrorDecoder = - Internal.errorDecoder errorCodeFromString + Json.map errorCodeFromString <| Json.field "error" Json.string {-| Json decoder for 'error\_description' field -} defaultErrorDescriptionDecoder : Json.Decoder (Maybe String) defaultErrorDescriptionDecoder = - Internal.errorDescriptionDecoder + Json.maybe <| Json.field "error_description" Json.string {-| Json decoder for 'error\_uri' field -} defaultErrorUriDecoder : Json.Decoder (Maybe String) defaultErrorUriDecoder = - Internal.errorUriDecoder + Json.maybe <| Json.field "error_uri" Json.string + + +{-| Combinator for JSON decoders to extract values from a `Maybe` or fail +with the given message (when `Nothing` is encountered) +-} +decoderFromJust : String -> Maybe a -> Json.Decoder a +decoderFromJust msg = + Maybe.map Json.succeed >> Maybe.withDefault (Json.fail msg) + + +{-| Combinator for JSON decoders to extact values from a `Result _ _` or fail +with an appropriate message +-} +decoderFromResult : Result String a -> Json.Decoder a +decoderFromResult res = + case res of + Err msg -> + Json.fail msg + + Ok a -> + Json.succeed a @@ -498,11 +578,11 @@ defaultErrorUriDecoder = -- -defaultFields : Internal.AuthenticationSuccess extraFields -> DefaultFields -defaultFields authenticationSuccess = - Internal.defaultFields authenticationSuccess +defaultFields : AuthenticationSuccess extraFields -> DefaultFields +defaultFields (AuthenticationSuccess defaultFields_ _) = + defaultFields_ -extraFields : Internal.AuthenticationSuccess extraFields -> extraFields -extraFields authenticationSuccess = - Internal.extraFields authenticationSuccess +extraFields : AuthenticationSuccess extraFields -> extraFields +extraFields (AuthenticationSuccess _ extraFields_) = + extraFields_ diff --git a/src/OAuth/AuthorizationCode.elm b/src/OAuth/AuthorizationCode.elm index 889d172..e5ba567 100644 --- a/src/OAuth/AuthorizationCode.elm +++ b/src/OAuth/AuthorizationCode.elm @@ -68,9 +68,9 @@ request. -} import Http -import Internal exposing (AuthenticationSuccess, authorizationErrorParser, defaultDecoder, errorParser, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, stateParser) +import Internal exposing (authorizationErrorParser, defaultDecoder, errorParser, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, stateParser) import Json.Decode as Json -import OAuth exposing (AuthorizationError, Default, ErrorCode, RequestParts, Token, errorCodeFromString) +import OAuth exposing (AuthenticationSuccess, AuthorizationError, Default, ErrorCode, RequestParts, Token, errorCodeFromString) import Url exposing (Url) import Url.Builder as Builder import Url.Parser as Url exposing (()) diff --git a/src/OAuth/AuthorizationCode/PKCE.elm b/src/OAuth/AuthorizationCode/PKCE.elm index c43fb53..d42659c 100644 --- a/src/OAuth/AuthorizationCode/PKCE.elm +++ b/src/OAuth/AuthorizationCode/PKCE.elm @@ -56,9 +56,9 @@ of this flow. import Base64.Encode as Base64 import Bytes exposing (Bytes) import Http -import Internal exposing (AuthenticationSuccess, authorizationErrorParser, errorParser, parseUrlQuery, stateParser) +import Internal exposing (authorizationErrorParser, defaultDecoder, errorParser, makeHeaders, makeRedirectUri, makeRequest, parseUrlQuery, stateParser) import Json.Decode as Json -import OAuth exposing (Default, ErrorCode, Token, errorCodeFromString) +import OAuth exposing (AuthenticationSuccess, Default, ErrorCode, RequestParts, Token, errorCodeFromString) import SHA256 as SHA256 import Url exposing (Url) import Url.Builder as Builder diff --git a/src/OAuth/ClientCredentials.elm b/src/OAuth/ClientCredentials.elm index b67e6cf..26fee6c 100644 --- a/src/OAuth/ClientCredentials.elm +++ b/src/OAuth/ClientCredentials.elm @@ -21,8 +21,9 @@ request. -} import Http -import Internal as Internal exposing (..) +import Internal exposing (defaultDecoder, makeHeaders, makeRequest, urlAddList) import Json.Decode as Json +import OAuth exposing (AuthenticationSuccess, Default, RequestParts) import Url exposing (Url) import Url.Builder as Builder @@ -69,7 +70,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (AuthenticationSuccess Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, scope, url } = let body = @@ -94,7 +95,7 @@ makeTokenRequest toMsg { credentials, scope, url } = req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request -} -makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, scope, url } = let body = diff --git a/src/OAuth/Implicit.elm b/src/OAuth/Implicit.elm index 7361eb2..03a7d37 100644 --- a/src/OAuth/Implicit.elm +++ b/src/OAuth/Implicit.elm @@ -266,7 +266,7 @@ defaultAuthorizationSuccessParser : Token -> Query.Parser (AuthorizationSuccess defaultAuthorizationSuccessParser accessToken = Query.map AuthorizationSuccess (defaultFieldsParser accessToken) - |> Query.map (\authorizationSuccess -> authorizationSuccess Internal.Default) + |> Query.map (\authorizationSuccess -> authorizationSuccess OAuth.Default) {-| Custom response success parser diff --git a/src/OAuth/Password.elm b/src/OAuth/Password.elm index 6972435..c81ec88 100644 --- a/src/OAuth/Password.elm +++ b/src/OAuth/Password.elm @@ -22,8 +22,9 @@ request. -} import Http -import Internal as Internal exposing (..) +import Internal exposing (defaultDecoder, makeHeaders, makeRequest, urlAddList) import Json.Decode as Json +import OAuth exposing (AuthenticationSuccess, Default, RequestParts) import Url exposing (Url) import Url.Builder as Builder @@ -75,7 +76,7 @@ type alias Credentials = req = makeTokenRequest toMsg authentication |> Http.request -} -makeTokenRequest : (Result Http.Error (Internal.AuthenticationSuccess Internal.Default) -> msg) -> Authentication -> RequestParts msg +makeTokenRequest : (Result Http.Error (AuthenticationSuccess Default) -> msg) -> Authentication -> RequestParts msg makeTokenRequest toMsg { credentials, password, scope, url, username } = let body = @@ -99,7 +100,7 @@ makeTokenRequest toMsg { credentials, password, scope, url, username } = req = makeTokenRequest extraFieldsDecoder toMsg authentication |> Http.request -} -makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (Internal.AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg +makeCustomTokenRequest : Json.Decoder extraFields -> (Result Http.Error (AuthenticationSuccess extraFields) -> msg) -> Authentication -> RequestParts msg makeCustomTokenRequest extraFieldsDecoder toMsg { credentials, password, scope, url, username } = let body = diff --git a/src/OAuth/Refresh.elm b/src/OAuth/Refresh.elm index 74b514c..9e3ad17 100644 --- a/src/OAuth/Refresh.elm +++ b/src/OAuth/Refresh.elm @@ -19,9 +19,9 @@ can be used in subsequent requests. -} import Http -import Internal exposing (AuthenticationSuccess, defaultDecoder, extractTokenString, makeHeaders, makeRequest, urlAddList) +import Internal exposing (defaultDecoder, extractTokenString, makeHeaders, makeRequest, urlAddList) import Json.Decode as Json -import OAuth exposing (Default, ErrorCode(..), RequestParts, Token) +import OAuth exposing (AuthenticationSuccess, Default, ErrorCode(..), RequestParts, Token) import Url exposing (Url) import Url.Builder as Builder From 1cb200b48f6ec86aa406c99cf30c363e5a1b77b6 Mon Sep 17 00:00:00 2001 From: adrianbunea Date: Wed, 16 Jun 2021 16:22:03 +0300 Subject: [PATCH 5/5] Reorder some OAuth.elm docs --- src/OAuth.elm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OAuth.elm b/src/OAuth.elm index 7a385d7..b06dbe0 100644 --- a/src/OAuth.elm +++ b/src/OAuth.elm @@ -4,7 +4,7 @@ module OAuth exposing , TokenType, TokenString, makeToken, makeRefreshToken , defaultAuthenticationSuccessDecoder, customAuthenticationSuccessDecoder, defaultAuthenticationErrorDecoder , defaultExpiresInDecoder, defaultScopeDecoder, defaultTokenDecoder, defaultRefreshTokenDecoder, defaultErrorDecoder, defaultErrorDescriptionDecoder, defaultErrorUriDecoder - , AuthenticationError, AuthenticationSuccess(..), AuthorizationError, Default(..), DefaultFields, RequestParts + , RequestParts, AuthenticationSuccess(..), DefaultFields, Default(..), AuthenticationError, AuthorizationError , defaultFields, extraFields , lenientScopeDecoder ) @@ -66,7 +66,7 @@ used. ## Authenticate -@docs AuthenticationError, AuthenticationSuccess, AuthorizationError, Default, DefaultFields, RequestParts +@docs RequestParts, AuthenticationSuccess, DefaultFields, Default, AuthenticationError, AuthorizationError ## Helpers