Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow extra fields to Authorization/Authentication Success #29

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 10 additions & 148 deletions src/Internal.elm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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 (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 (..)
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
Expand All @@ -12,117 +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 AuthenticationSuccess
authenticationSuccessDecoder =
Json.map4 AuthenticationSuccess
tokenDecoder
refreshTokenDecoder
expiresInDecoder
scopeDecoder


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
defaultDecoder : Json.Decoder Default
defaultDecoder =
Json.succeed OAuth.Default



Expand All @@ -131,7 +27,7 @@ decoderFromResult res =
--


authorizationErrorParser : e -> Query.Parser (AuthorizationError e)
authorizationErrorParser : ErrorCode -> Query.Parser AuthorizationError
authorizationErrorParser errorCode =
Query.map3 (AuthorizationError errorCode)
errorDescriptionParser
Expand Down Expand Up @@ -245,13 +141,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 (customAuthenticationSuccessDecoder extraFieldsDecoder)
, timeout = Nothing
, tracker = Nothing
}
Expand Down Expand Up @@ -341,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
Expand All @@ -360,26 +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 alias AuthenticationSuccess =
{ token : Token
, refreshToken : Maybe Token
, expiresIn : Maybe Int
, scope : List String
}


type alias AuthenticationError e =
{ error : e
, errorDescription : Maybe String
, errorUri : Maybe String
}
Loading