solcates / solcates-elm-oauth2 / OAuth.AuthorizationCode

The authorization code grant type is used to obtain both access tokens and refresh tokens and is optimized for confidential clients. Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.

   +---------+                                +--------+
   |         |---(A)- Auth Redirection ------>|        |
   |         |                                |  Auth  |
   | Browser |                                | Server |
   |         |                                |        |
   |         |<--(B)- Redirection Callback ---|        |
   +---------+          (w/ Auth Code)        +--------+
     ^     |                                    ^    |
     |     |                                    |    |
    (A)   (B)                                   |    |
     |     |                                    |    |
     |     v                                    |    |
   +---------+                                  |    |
   |         |----(C)---- Auth Code ------------+    |
   | Elm App |                                       |
   |         |                                       |
   |         |<---(D)------ Access Token ------------+
   +---------+       (w/ Optional Refresh Token)

After those steps, the client owns a Token that can be used to authorize any subsequent request.

Authorize

makeAuthorizationUrl : Authorization -> Url

Redirects the resource owner (user) to the resource provider server using the specified authorization flow.

parseCode : Url -> AuthorizationResult

Parse the location looking for a parameters set by the resource provider server after redirecting the resource owner (user).

Returns AuthorizationResult Empty when there's nothing


type alias Authorization =
{ clientId : String
, url : Url
, redirectUri : Url
, scope : List String
, state : Maybe String 
}

Request configuration for an authorization (Authorization Code & Implicit flows)


type alias AuthorizationCode =
String

A simple type alias to ease readability of type signatures


type AuthorizationResult
    = Empty
    | Error AuthorizationError
    | Success AuthorizationSuccess

Describes errors coming from attempting to parse a url after an OAuth redirection


type alias AuthorizationSuccess =
{ code : AuthorizationCode
, state : Maybe String 
}

The response obtained as a result of an authorization


type alias AuthorizationError =
{ error : OAuth.ErrorCode
, errorDescription : Maybe String
, errorUri : Maybe String
, state : Maybe String 
}

Describes an OAuth error as a result of an authorization request failure

Authenticate

makeTokenRequest : (Result Http.Error AuthenticationSuccess -> msg) -> Authentication -> RequestParts msg

Builds a the request components required to get a token from an authorization code

let req : Http.Request AuthenticationSuccess
    req = makeTokenRequest toMsg authentication |> Http.request


type alias Authentication =
{ credentials : Credentials
, code : String
, redirectUri : Url
, url : Url 
}

Request configuration for an AuthorizationCode authentication


type alias Credentials =
{ clientId : String
, secret : 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 the authentication request. Provides it if you need to do so.

  { clientId = "<my-client-id>"
  , secret = Just "<my-client-secret>"
  }


type alias AuthenticationSuccess =
{ token : OAuth.Token
, refreshToken : Maybe OAuth.Token
, expiresIn : Maybe Basics.Int
, scope : List String 
}

The response obtained as a result of an authentication (implicit or not)


type alias AuthenticationError =
{ error : OAuth.ErrorCode
, errorDescription : Maybe String
, errorUri : Maybe String 
}

Describes an OAuth error as a result of a request failure


type alias RequestParts a =
{ method : String
, headers : List Http.Header
, url : String
, body : Http.Body
, expect : Http.Expect a
, timeout : Maybe Basics.Float
, tracker : 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.

JSON Decoders

defaultAuthenticationSuccessDecoder : Json.Decode.Decoder AuthenticationSuccess

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.

defaultAuthenticationSuccessDecoder : Decoder AuthenticationSuccess
defaultAuthenticationSuccessDecoder =
    D.map4 AuthenticationSuccess
        tokenDecoder
        refreshTokenDecoder
        expiresInDecoder
        scopeDecoder

defaultAuthenticationErrorDecoder : Json.Decode.Decoder AuthenticationError

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

JSON Decoders (advanced)

defaultExpiresInDecoder : Json.Decode.Decoder (Maybe Basics.Int)

Json decoder for an 'expire' timestamp

defaultScopeDecoder : Json.Decode.Decoder (List String)

Json decoder for a 'scope'

lenientScopeDecoder : Json.Decode.Decoder (List String)

Json decoder for a 'scope', allowing comma- or space-separated scopes

defaultTokenDecoder : Json.Decode.Decoder OAuth.Token

Json decoder for an 'access_token'

defaultRefreshTokenDecoder : Json.Decode.Decoder (Maybe OAuth.Token)

Json decoder for a 'refresh_token'

defaultErrorDecoder : Json.Decode.Decoder OAuth.ErrorCode

Json decoder for 'error' field

defaultErrorDescriptionDecoder : Json.Decode.Decoder (Maybe String)

Json decoder for 'error_description' field

defaultErrorUriDecoder : Json.Decode.Decoder (Maybe String)

Json decoder for 'error_uri' field

Query Parsers (advanced)

parseCodeWith : Parsers -> Url -> AuthorizationResult

See parseCode, but gives you the ability to provide your own custom parsers.


type alias Parsers =
{ codeParser : Url.Parser.Query.Parser (Maybe String)
, errorParser : Url.Parser.Query.Parser (Maybe OAuth.ErrorCode)
, authorizationSuccessParser : String -> Url.Parser.Query.Parser AuthorizationSuccess
, authorizationErrorParser : OAuth.ErrorCode -> Url.Parser.Query.Parser AuthorizationError 
}

Parsers used in the 'parseCode' function.

defaultParsers : Parsers

Default parsers according to RFC-6749

defaultCodeParser : Url.Parser.Query.Parser (Maybe String)

Default 'code' parser according to RFC-6749

defaultErrorParser : Url.Parser.Query.Parser (Maybe OAuth.ErrorCode)

Default 'error' parser according to RFC-6749

defaultAuthorizationSuccessParser : String -> Url.Parser.Query.Parser AuthorizationSuccess

Default response success parser according to RFC-6749

defaultAuthorizationErrorParser : OAuth.ErrorCode -> Url.Parser.Query.Parser AuthorizationError

Default response error parser according to RFC-6749