diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.5
+---
+
+* Add JwtEncoding type. Changes API of `Jwt.encode` and `Jwt.decode`.
+
 0.4.2
 -----
 
diff --git a/Jose/Jwt.hs b/Jose/Jwt.hs
--- a/Jose/Jwt.hs
+++ b/Jose/Jwt.hs
@@ -14,8 +14,8 @@
 -- >>> g <- makeSystem
 -- >>> let jsonJwk = "{\"kty\":\"RSA\", \"kid\":\"mykey\", \"n\":\"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ\", \"e\":\"AQAB\", \"d\":\"Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ\"}" :: ByteString
 -- >>> let Just jwk = decodeStrict jsonJwk :: Maybe Jwk
--- >>> let (Right (Jwt jwtEncoded), g')  = encode g [jwk] (Signed RS256) Nothing (Claims "public claims")
--- >>> let (Right jwtDecoded, g'') = Jose.Jwt.decode g' [jwk] jwtEncoded
+-- >>> let (Right (Jwt jwtEncoded), g')  = encode g [jwk] (JwsEncoding RS256) (Claims "public claims")
+-- >>> let (Right jwtDecoded, g'') = Jose.Jwt.decode g' [jwk] (Just (JwsEncoding RS256)) jwtEncoded
 -- >>> jwtDecoded
 -- Jws (JwsHeader {jwsAlg = RS256, jwsTyp = Nothing, jwsCty = Nothing, jwsKid = Just "mykey"},"public claims")
 
@@ -49,45 +49,45 @@
 
 -- | Use the supplied JWKs to create a JWT.
 -- The list of keys will be searched to locate one which is
--- consistent with the chosen algorithm.
+-- consistent with the chosen encoding algorithms.
 --
 encode :: (CPRG g)
-       => g                          -- ^ Random number generator.
+       => g                          -- ^ Random number generator
        -> [Jwk]                      -- ^ The key or keys. At least one must be consistent with the chosen algorithm
-       -> Alg                        -- ^ The JWS or JWE algorithm
-       -> Maybe Enc                  -- ^ The payload encryption algorithm (if applicable)
+       -> JwtEncoding                -- ^ The encoding algorithm(s) used to encode the payload
        -> Payload                    -- ^ The payload (claims)
        -> (Either JwtError Jwt, g)   -- ^ The encoded JWT, if successful
-encode rng jwks alg enc msg = flip runState rng $ runEitherT $ case alg of
-    Signed None -> do
-        unless (isNothing enc) $ left (BadAlgorithm "Enc cannot be set for an unsecured JWT")
-        case msg of
-            Claims p -> return $ Jwt $ BC.intercalate "." [unsecuredHdr, B64.encode p]
-            Nested _ -> left BadClaims
-    Signed a    -> do
-        unless (isNothing enc) $ left (BadAlgorithm "Enc cannot be set for a JWS")
-        case filter (canEncodeJws a) jwks of
-            []    -> left (KeyError "No matching key found for JWS algorithm")
-            (k:_) -> hoistEither =<< state (\g -> Jws.jwkEncode g a k msg)
-    Encrypted a -> do
-        e <- hoistEither $ note (BadAlgorithm "Enc must be supplied for a JWE") enc
-        case filter (canEncodeJwe a) jwks of
-            []    -> left (KeyError "No matching key found for JWE algorithm")
-            (k:_) -> hoistEither =<< state (\g -> Jwe.jwkEncode g a e k msg)
+encode rng jwks encoding msg = flip runState rng $ runEitherT $ case encoding of
+    JwsEncoding None -> case msg of
+        Claims p -> return $ Jwt $ BC.intercalate "." [unsecuredHdr, B64.encode p]
+        Nested _ -> left BadClaims
+    JwsEncoding a    -> case filter (canEncodeJws a) jwks of
+        []    -> left (KeyError "No matching key found for JWS algorithm")
+        (k:_) -> hoistEither =<< state (\g -> Jws.jwkEncode g a k msg)
+    JweEncoding a e -> case filter (canEncodeJwe a) jwks of
+        []    -> left (KeyError "No matching key found for JWE algorithm")
+        (k:_) -> hoistEither =<< state (\g -> Jwe.jwkEncode g a e k msg)
   where
     unsecuredHdr = B64.encode "{\"alg\":\"none\"}"
 
 
 -- | Uses the supplied keys to decode a JWT.
 -- Locates a matching key by header @kid@ value where possible
--- or by suitable key type.
--- The JWK @use@ and @alg@ options are currently ignored.
+-- or by suitable key type for the encoding algorithm.
+--
+-- The algorithm(s) used can be optionally be supplied for validation
+-- by setting the @JwtEncoding@ parameter, in which case an error will
+-- be returned if they don't match.
+--
+-- For unsecured tokens (with algorithm "none"), the expected algorithm
+-- must be set to @Just (JwsEncoding None)@ or an error will be returned.
 decode :: CPRG g
        => g                               -- ^ Random number generator. Only used for RSA blinding
        -> [Jwk]                           -- ^ The keys to use for decoding
+       -> Maybe JwtEncoding               -- ^ The expected encoding information
        -> ByteString                      -- ^ The encoded JWT
        -> (Either JwtError JwtContent, g) -- ^ The decoded JWT payload, if successful
-decode rng keySet jwt = flip runState rng $ runEitherT $ do
+decode rng keySet encoding jwt = flip runState rng $ runEitherT $ do
     let components = BC.split '.' jwt
     when (length components < 3) $ left $ BadDots 2
     hdr <- B64.decode (head components) >>= hoistEither . parseHeader
@@ -95,9 +95,15 @@
     -- Now we have one or more suitable keys (or none for the unsecured case).
     -- Try each in turn until successful
     decodings <- case hdr of
-        UnsecuredH -> B64.decode (components !! 1) >>= \p -> return [Just (Unsecured p)]
-        JwsH _     -> mapM decodeWithJws ks
-        JweH _     -> mapM decodeWithJwe ks
+        UnsecuredH -> do
+            unless (encoding == Just (JwsEncoding None)) $ left (BadAlgorithm "JWT is unsecured but expected 'alg' was not 'none'")
+            B64.decode (components !! 1) >>= \p -> return [Just (Unsecured p)]
+        JwsH h     -> do
+            unless (isNothing encoding || encoding == Just (JwsEncoding (jwsAlg h))) $ left (BadAlgorithm "Expected 'alg' doesn't match JWS header")
+            mapM decodeWithJws ks
+        JweH h     -> do
+            unless (isNothing encoding || encoding == Just (JweEncoding (jweAlg h) (jweEnc h))) $ left (BadAlgorithm "Expected encoding doesn't match JWE header")
+            mapM decodeWithJwe ks
     maybe (left $ KeyError "None of the keys was able to decode the JWT") (return . fromJust) $ find isJust decodings
   where
     decodeWithJws :: CPRG g => Jwk -> EitherT JwtError (State g) (Maybe JwtContent)
@@ -142,4 +148,3 @@
     -- TODO Move checks to JWK and support better error messages
     checkKeys [] = left $ KeyError "No suitable key was found to decode the JWT"
     checkKeys ks = return ks
-
diff --git a/Jose/Types.hs b/Jose/Types.hs
--- a/Jose/Types.hs
+++ b/Jose/Types.hs
@@ -10,6 +10,7 @@
     , JwsHeader (..)
     , JweHeader (..)
     , JwtContent (..)
+    , JwtEncoding (..)
     , JwtError (..)
     , IntDate (..)
     , Payload (..)
@@ -54,6 +55,14 @@
 
 -- | A decoded JWT which can be either a JWE or a JWS, or an unsecured JWT.
 data JwtContent = Unsecured !ByteString | Jws !Jws | Jwe !Jwe deriving (Show, Eq)
+
+-- | Defines the encoding information for a JWT.
+--
+-- Used for both encoding new JWTs and validating existing ones.
+data JwtEncoding
+    = JwsEncoding JwsAlg
+    | JweEncoding JweAlg Enc
+      deriving (Eq, Show)
 
 data JwtHeader = JweH JweHeader
                | JwsH JwsHeader
diff --git a/jose-jwt.cabal b/jose-jwt.cabal
--- a/jose-jwt.cabal
+++ b/jose-jwt.cabal
@@ -1,5 +1,5 @@
 Name:               jose-jwt
-Version:            0.4.2
+Version:            0.5
 Synopsis:           JSON Object Signing and Encryption Library
 Homepage:           http://github.com/tekul/jose-jwt
 Bug-Reports:        http://github.com/tekul/jose-jwt/issues
diff --git a/tests/Tests/JweSpec.hs b/tests/Tests/JweSpec.hs
--- a/tests/Tests/JweSpec.hs
+++ b/tests/Tests/JweSpec.hs
@@ -41,7 +41,7 @@
         generateCmkAndIV g A256GCM @?= (a1cek, a1iv, RNG "")
 
       it "generates the expected RSA-encrypted content key" $ do
-        let g = RNG $ a1oaepSeed
+        let g = RNG a1oaepSeed
         rsaEncrypt g RSA_OAEP a1PubKey a1cek @?= (a1jweKey, RNG "")
 
       it "encrypts the payload to the expected ciphertext and authentication tag" $ do
@@ -52,8 +52,8 @@
         let g = RNG $ B.concat [a1cek, a1iv, a1oaepSeed]
         Jwe.rsaEncode g RSA_OAEP A256GCM a1PubKey a1Payload @?= (Jwt a1, RNG "")
 
-      it "decodes the JWT to the expected header and payload" $ do
-        (fst $ Jwe.rsaDecode blinderRNG a1PrivKey a1) @?= Right (a1Header, a1Payload)
+      it "decodes the JWT to the expected header and payload" $
+        fst (Jwe.rsaDecode blinderRNG a1PrivKey a1) @?= Right (a1Header, a1Payload)
 
       it "decodes the JWK to the correct RSA key values" $ do
         let Right (Jwk.RsaPrivateJwk (RSA.PrivateKey pubKey d 0 0 0 0 0) _ _ _) = eitherDecode a1jwk
@@ -64,7 +64,7 @@
       it "decodes the JWT using the JWK" $ do
         let Right k1 = eitherDecode a1jwk
             Just  k2 = decodeStrict' a2jwk
-        fst (decode blinderRNG [k2, k1] a1) @?= (Right $ Jwe (a1Header, a1Payload))
+        fst (decode blinderRNG [k2, k1] (Just $ JweEncoding RSA_OAEP A256GCM) a1) @?= (Right $ Jwe (a1Header, a1Payload))
 
     context "when using JWE Appendix 2 data" $ do
       let a2Header = defJweHdr {jweAlg = RSA1_5, jweEnc = A128CBC_HS256}
@@ -247,4 +247,3 @@
  -- Decrypt, drop the 02 at the start and take the bytes up to the next 0
 extractPKCS15Seed :: RSA.PrivateKey -> B.ByteString -> B.ByteString
 extractPKCS15Seed key ct = B.takeWhile (/= 0) . B.drop 2 $ dp Nothing key ct
-
diff --git a/tests/Tests/JwsSpec.hs b/tests/Tests/JwsSpec.hs
--- a/tests/Tests/JwsSpec.hs
+++ b/tests/Tests/JwsSpec.hs
@@ -46,7 +46,7 @@
 
         it "decodes the payload using the JWK" $ do
           let Just k11 = decodeStrict' a11jwk
-          fst (decode RNG [k11] a11) @?= fmap Jws a11decoded
+          fst (decode RNG [k11] Nothing a11) @?= fmap Jws a11decoded
 
         it "encodes/decodes using HS512" $
           hmacRoundTrip HS512 a11Payload
@@ -60,7 +60,7 @@
 
         it "decodes the JWT to the expected header and payload with the JWK" $ do
           let Just k21 = decodeStrict' a21jwk
-          fst (decode RNG [k21] a21) @?= (Right $ Jws (defJwsHdr {jwsAlg = RS256}, a21Payload))
+          fst (decode RNG [k21] (Just (JwsEncoding RS256)) a21) @?= (Right $ Jws (defJwsHdr {jwsAlg = RS256}, a21Payload))
 
         it "encodes the payload to the expected JWT" $ do
           let sign = either (error "Sign failed") id . RSAPKCS15.sign Nothing hashDescrSHA256 rsaPrivateKey
@@ -79,11 +79,15 @@
         let a31decoded = Right (defJwsHdr {jwsAlg = ES256}, a31Payload)
         it "decodes the JWT to the expected header and payload" $ do
           let Just k31 = decodeStrict' a31jwk
-          fst (decode RNG [k31] a31) @?= fmap Jws a31decoded
+          fst (decode RNG [k31] Nothing a31) @?= fmap Jws a31decoded
 
-      context "when using an unsecured JWT" $
+      context "when using an unsecured JWT" $ do
+        it "returns an error if alg is unset" $
+          fst (decode RNG [] Nothing jwt61) @?= Left (BadAlgorithm "JWT is unsecured but expected 'alg' was not 'none'")
+        it "returns an error if alg is is not 'none'" $
+          fst (decode RNG [] (Just (JwsEncoding RS256)) jwt61) @?= Left (BadAlgorithm "JWT is unsecured but expected 'alg' was not 'none'")
         it "decodes the JWT to the expected header and payload" $
-          fst (decode RNG [] jwt61) @?= Right (Unsecured jwt61Payload)
+          fst (decode RNG [] (Just (JwsEncoding None)) jwt61) @?= Right (Unsecured jwt61Payload)
 
 
 signWithHeader sign hdr payload = B.intercalate "." [hdrPayload, B64.encode $ sign hdrPayload]
@@ -152,4 +156,3 @@
     }
 
 a11mac = hmac SHA256.hash 64 hmacKey
-
