diff --git a/fission-cli/library/Fission/CLI/Environment/Types.hs b/fission-cli/library/Fission/CLI/Environment/Types.hs index a1edf19ff..9774cdf97 100644 --- a/fission-cli/library/Fission/CLI/Environment/Types.hs +++ b/fission-cli/library/Fission/CLI/Environment/Types.hs @@ -27,6 +27,7 @@ data Env = Env -- Releases , updateChecked :: UTCTime } + deriving (Eq, Show) instance ToJSON Env where toJSON Env {..} = object diff --git a/fission-cli/library/Fission/CLI/Handler/User/Login.hs b/fission-cli/library/Fission/CLI/Handler/User/Login.hs index 220d15ad9..ed86bdf4f 100644 --- a/fission-cli/library/Fission/CLI/Handler/User/Login.hs +++ b/fission-cli/library/Fission/CLI/Handler/User/Login.hs @@ -107,14 +107,8 @@ login optUsername = do baseURL = rootURL {baseUrlPath = "/user/link"} attempt ensureNotLoggedIn >>= \case - Right () -> - consume signingSK baseURL optUsername - - Left err -> do - -- TODO replace below with `produce signingSK baseURL` when auth lobby can handle EdDSA - Env {username} <- Env.get - logUser $ "Already logged in as " <> textDisplay username - raise err + Right () -> consume signingSK baseURL optUsername + Left _ -> produce signingSK baseURL type ConsumerConstraints m = ( MonadIO m @@ -175,7 +169,7 @@ consume signingSK baseURL optUsername = do sessionDID = DID Key (RSAPublicKey pk) logDebug @Text "🤝 Device linking handshake: Step 2" - broadcastRaw conn sessionDID + broadcastApiData conn sessionDID reattempt 10 do logDebug @Text "🤝 Device linking handshake: Step 3" @@ -189,7 +183,7 @@ consume signingSK baseURL optUsername = do -- TODO waiting on FE to not send an append UCAN -- case (jwt |> claims |> potency) == AuthNOnly of ensure $ UCAN.containsFact jwt \facts -> - if any (== SessionKey sessionKey) facts + if SessionKey sessionKey `elem` facts then Right () else Left JWT.Proof.MissingExpectedFact @@ -304,24 +298,32 @@ produce signingSK baseURL = do logDebug @Text "🤝 Device linking handshake: Step 5" PIN.Payload requestorDID pin <- secureListenJSON aesConn - pinOK <- reaskYN $ "Does this code match your second device? " <> textDisplay pin + pinOK <- reaskYN $ "🔢 Does this code match your second device? " <> textDisplay pin unless pinOK do raise $ Mismatch @PIN reattempt 100 do logDebug @Text "🤝 Device linking handshake: Step 6" - (_, readKey) <- WebNative.FileSystem.Auth.Store.getMostPrivileged rootDID "/" + readKey <- do + attempt (WebNative.FileSystem.Auth.Store.getMostPrivileged rootDID "/") >>= \case + Left _ -> + case rootProof of + RootCredential -> WebNative.FileSystem.Auth.Store.create rootDID "/" + _ -> raise $ NotFound @(Symmetric.Key AES256) + + Right (_, key) -> + return key let jwt = delegateSuperUser requestorDID signingSK rootProof now bearer = Bearer.fromJWT jwt - accessOK <- reaskYN $ "Grant access to: " <> JWT.prettyPrintGrants jwt + accessOK <- reaskYN $ "🧞 Grant access? " <> JWT.prettyPrintGrants jwt unless accessOK $ raise (Status Denied) aesConn `secureBroadcastJSON` User.Link.Payload {bearer, readKey} - UTF8.putTextLn "Login to other device successful 👍" + UTF8.putTextLn "🤝 Login to other device successful 🎉" return username diff --git a/fission-cli/library/Fission/CLI/Handler/User/Register.hs b/fission-cli/library/Fission/CLI/Handler/User/Register.hs index 97c6576f2..47b4f94bc 100644 --- a/fission-cli/library/Fission/CLI/Handler/User/Register.hs +++ b/fission-cli/library/Fission/CLI/Handler/User/Register.hs @@ -1,9 +1,9 @@ -- | Setup command module Fission.CLI.Handler.User.Register (register) where -import qualified Data.Yaml as YAML +import qualified Data.Yaml as YAML -import qualified Crypto.PubKey.Ed25519 as Ed25519 +import qualified Crypto.PubKey.Ed25519 as Ed25519 import Crypto.Random import Network.DNS @@ -14,28 +14,30 @@ import Fission.Prelude import Fission.Authorization.ServerDID import Fission.Error.Types -import Fission.Key.Error as Key +import Fission.Key as Key import Fission.User.Username.Types import Fission.Web.Auth.Token.JWT.Types import Fission.Web.Auth.Token.Types -import Fission.Web.Client as Client -import qualified Fission.Web.Client.User as User +import Fission.Web.Client as Client +import qualified Fission.Web.Client.User as User import Fission.User.DID.Types import Fission.User.Email.Types import Fission.User.Registration.Types -import qualified Fission.User.Username.Error as Username +import qualified Fission.User.Username.Error as Username import Fission.CLI.Remote -import Fission.CLI.Display.Error as CLI.Error -import Fission.CLI.Display.Success as CLI.Success +import Fission.CLI.Display.Error as CLI.Error +import Fission.CLI.Display.Success as CLI.Success -import Fission.CLI.Environment as Env -import Fission.CLI.Key.Store as KeyStore -import qualified Fission.CLI.Prompt as Prompt -import Fission.CLI.WebNative.Mutation.Auth.Store as UCAN +import Fission.CLI.Environment as Env +import Fission.CLI.Key.Store as KeyStore +import qualified Fission.CLI.Prompt as Prompt + +import qualified Fission.CLI.WebNative.FileSystem.Auth.Store as WNFS +import Fission.CLI.WebNative.Mutation.Auth.Store as UCAN register :: ( MonadIO m @@ -47,6 +49,7 @@ register :: , MonadTime m , MonadRandom m , ServerDID m + , WNFS.MonadStore m , MonadWebAuth m Token , MonadWebAuth m (SecretKey SigningKey) @@ -90,6 +93,7 @@ createAccount :: , MonadTime m , ServerDID m , MonadRandom m + , WNFS.MonadStore m , MonadWebAuth m Token , MonadWebAuth m Ed25519.SecretKey @@ -118,8 +122,9 @@ createAccount maybeUsername maybeEmail = do Nothing -> Email <$> Prompt.reaskNotEmpty' "Email:" Just mail -> return mail - exchangeSK <- KeyStore.fetch $ Proxy @ExchangeKey - exchangePK <- KeyStore.toPublic (Proxy @ExchangeKey) exchangeSK + exchangePK <- KeyStore.fetchPublic (Proxy @ExchangeKey) + signingPK <- KeyStore.fetchPublic (Proxy @SigningKey) + _ <- WNFS.create (DID Key $ Ed25519PublicKey signingPK) "/" let form = Registration diff --git a/fission-cli/library/Fission/CLI/Key/Store.hs b/fission-cli/library/Fission/CLI/Key/Store.hs index 86555d86f..62d73e367 100644 --- a/fission-cli/library/Fission/CLI/Key/Store.hs +++ b/fission-cli/library/Fission/CLI/Key/Store.hs @@ -2,6 +2,7 @@ module Fission.CLI.Key.Store ( create , forceCreate , fetch + , fetchPublic , delete , persist , exists @@ -78,6 +79,18 @@ fetch keyRole = do scrubbed <- getAsBytes keyRole ensureM $ parse keyRole scrubbed +fetchPublic :: + ( MonadIO m + , MonadKeyStore m key + , MonadRaise m + , m `Raises` Key.Error + ) + => Proxy key + -> m (PublicKey key) +fetchPublic keyRole = do + sk <- fetch keyRole + toPublic keyRole sk + getAsBytes :: ( MonadIO m , MonadKeyStore m key diff --git a/fission-cli/library/Fission/CLI/PIN/Payload/Types.hs b/fission-cli/library/Fission/CLI/PIN/Payload/Types.hs index 4cd74d58f..67fba2bc6 100644 --- a/fission-cli/library/Fission/CLI/PIN/Payload/Types.hs +++ b/fission-cli/library/Fission/CLI/PIN/Payload/Types.hs @@ -1,5 +1,7 @@ module Fission.CLI.PIN.Payload.Types (Payload (..)) where +import Servant.API + import Fission.Prelude import Fission.User.DID.Types @@ -24,3 +26,9 @@ instance FromJSON Payload where did <- obj .: "did" pin <- obj .: "pin" return Payload {..} + +instance MimeRender OctetStream Payload where + mimeRender _ payload = encode payload + +instance MimeUnrender OctetStream Payload where + mimeUnrender _ lbs = eitherDecode lbs diff --git a/fission-cli/library/Fission/CLI/PIN/Types.hs b/fission-cli/library/Fission/CLI/PIN/Types.hs index fad6ecb5f..bf137787e 100644 --- a/fission-cli/library/Fission/CLI/PIN/Types.hs +++ b/fission-cli/library/Fission/CLI/PIN/Types.hs @@ -3,6 +3,8 @@ module Fission.CLI.PIN.Types (PIN (..)) where import qualified RIO.Text as Text import qualified RIO.Vector as Vector +import Servant.API + import Fission.Prelude import Fission.Emoji.Class @@ -59,3 +61,9 @@ instance FromJSON PIN where instance Display (Mismatch PIN) where display _ = "PIN codes do not match" + +instance MimeRender OctetStream PIN where + mimeRender _ pin = encode pin + +instance MimeUnrender OctetStream PIN where + mimeUnrender _ lbs = eitherDecode lbs diff --git a/fission-cli/library/Fission/CLI/PubSub.hs b/fission-cli/library/Fission/CLI/PubSub.hs index a2dc3d471..8969fa093 100644 --- a/fission-cli/library/Fission/CLI/PubSub.hs +++ b/fission-cli/library/Fission/CLI/PubSub.hs @@ -2,7 +2,7 @@ module Fission.CLI.PubSub ( listenJSON , listenRaw , broadcastJSON - , broadcastRaw + , broadcastApiData , module Fission.CLI.PubSub.Class , module Fission.CLI.PubSub.Topic.Types ) where @@ -47,6 +47,6 @@ listenRaw conn = do broadcastJSON :: (MonadPubSub m, ToJSON msg) => Connection m -> msg -> m () broadcastJSON conn msg = sendLBS conn $ encode msg -broadcastRaw :: (MonadPubSub m, ToHttpApiData msg) => Connection m -> msg -> m () -broadcastRaw conn msg = +broadcastApiData :: (MonadPubSub m, ToHttpApiData msg) => Connection m -> msg -> m () +broadcastApiData conn msg = sendLBS conn . Binary.toLazyByteString $ toEncodedUrlPiece msg diff --git a/fission-cli/library/Fission/CLI/Types.hs b/fission-cli/library/Fission/CLI/Types.hs index 2dc7a5718..0f2f323b9 100644 --- a/fission-cli/library/Fission/CLI/Types.hs +++ b/fission-cli/library/Fission/CLI/Types.hs @@ -13,7 +13,8 @@ import qualified Crypto.PubKey.RSA as RSA import qualified Crypto.PubKey.RSA.OAEP as RSA.OAEP import Crypto.Random -import Data.ByteArray as ByteArray hiding (any) +import Data.ByteArray as ByteArray hiding + (any) import qualified Data.Yaml as YAML import Control.Monad.Base @@ -39,6 +40,8 @@ import qualified Network.IPFS.Process.Error as Process import Network.IPFS.Types as IPFS import qualified Network.WebSockets.Client as WS +import Servant.API hiding + (IsMember) import Servant.Client import qualified Wuss as WSS @@ -281,7 +284,7 @@ instance storePath `JSON.writeFile` WebNative.FileSystem.Auth.Store newGlobalStore getAllMatching did subGraphRoot = do - logDebug $ "Looking up AES key for " <> display did <> " @ " <> displayShow subGraphRoot + logDebug $ "👀 🔑 Looking up AES keys matching " <> display did <> " @ " <> displayShow subGraphRoot storePath <- wnfsKeyStorePath storeOrErr <- attempt $ JSON.readFile storePath @@ -519,7 +522,7 @@ instance | cmd == Just "pin" || cmd == Just "add" -> (Nothing, opts' <> [arg', timeout, cidVersion, ignore]) | otherwise -> (Nothing, opts' <> [arg', timeout]) - processStr = intercalate " " ("IPFS_PATH=" <> ipfsRepo : ipfs : opts) + processStr = unwords ("IPFS_PATH=" <> ipfsRepo : ipfs : opts) rawProcess = fromString processStr process = case pipeArg of @@ -729,10 +732,10 @@ instance forall errs cfg . let Symmetric.Key aesClear = sessionKey - ucan = Bearer.BareToken bearerToken + token = Bearer.BareToken bearerToken iv <- ensureM Symmetric.genIV - msg <- ensure $ Symmetric.encrypt sessionKey iv ucan + msg <- ensure $ Symmetric.encrypt sessionKey iv token encryptedAES <- ensureM $ RSA.OAEP.encrypt oaepParams rsaPK aesClear return PubSub.Handshake { iv @@ -767,8 +770,8 @@ oaepParams = RSA.OAEP.defaultOAEPParams SHA256 instance forall errs cfg msg . ( HasLogFunc cfg - , ToJSON msg - , FromJSON msg + , MimeRender OctetStream msg + , MimeUnrender OctetStream msg , IV.GenError `IsMember` errs , CryptoError `IsMember` errs , Display (OpenUnion errs) @@ -784,8 +787,8 @@ instance forall errs cfg msg . Left cryptoError -> return . Left $ CannotDecrypt cryptoError - Right bs -> - case eitherDecodeStrict bs of + Right lbs -> + case mimeUnrender (Proxy @OctetStream) $ Lazy.fromStrict lbs of Left err -> return . Left $ UnableToDeserialize err Right a -> return $ Right a diff --git a/fission-cli/library/Fission/CLI/User/Link/Payload/Types.hs b/fission-cli/library/Fission/CLI/User/Link/Payload/Types.hs index 02069b719..7a3db6b05 100644 --- a/fission-cli/library/Fission/CLI/User/Link/Payload/Types.hs +++ b/fission-cli/library/Fission/CLI/User/Link/Payload/Types.hs @@ -2,6 +2,8 @@ module Fission.CLI.User.Link.Payload.Types (Payload (..)) where import Crypto.Cipher.AES (AES256) +import Servant.API + import Fission.Prelude import qualified Fission.Key.Symmetric.Types as Symmetric @@ -14,9 +16,9 @@ data Payload = Payload deriving Eq instance ToJSON Payload where - toJSON Payload {readKey, bearer = Bearer.Token {rawContent}} = + toJSON Payload {readKey, bearer} = object [ "readKey" .= readKey - , "ucan" .= rawContent + , "ucan" .= BareToken bearer ] instance FromJSON Payload where @@ -26,3 +28,9 @@ instance FromJSON Payload where bearer <- parseJSON $ String ("bearer " <> rawUCAN) return Payload {..} + +instance MimeRender OctetStream Payload where + mimeRender _ payload = encode payload + +instance MimeUnrender OctetStream Payload where + mimeUnrender _ lbs = eitherDecode lbs diff --git a/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store.hs b/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store.hs index 006cefd5d..58285a902 100644 --- a/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store.hs +++ b/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store.hs @@ -1,5 +1,6 @@ module Fission.CLI.WebNative.FileSystem.Auth.Store - ( getLeastPrivileged + ( create + , getLeastPrivileged , getMostPrivileged -- * Reexports , module Fission.CLI.WebNative.FileSystem.Auth.Store.Class @@ -7,17 +8,34 @@ module Fission.CLI.WebNative.FileSystem.Auth.Store ) where import Crypto.Cipher.AES (AES256) +import Crypto.Random.Types import qualified RIO.Map as Map import Fission.Prelude import Fission.Error.NotFound.Types -import qualified Fission.Key.Symmetric.Types as Symmetric +import qualified Fission.Key.Symmetric as Symmetric import Fission.User.DID.Types -import Fission.CLI.WebNative.FileSystem.Auth.Store.Class +import qualified Fission.CLI.WebNative.FileSystem.Auth.Store.Class as WNFS.Auth import Fission.CLI.WebNative.FileSystem.Auth.Store.Types +-- Reexport + +import Fission.CLI.WebNative.FileSystem.Auth.Store.Class + +create :: + ( MonadRandom m + , MonadStore m + ) + => DID + -> FilePath + -> m (Symmetric.Key AES256) +create did path = do + key <- Symmetric.genAES256 + WNFS.Auth.set did path key + return key + getLeastPrivileged :: ( MonadStore m , MonadRaise m diff --git a/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store/Types.hs b/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store/Types.hs index cbe9bdfa5..66c81a663 100644 --- a/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store/Types.hs +++ b/fission-cli/library/Fission/CLI/WebNative/FileSystem/Auth/Store/Types.hs @@ -7,7 +7,5 @@ import Fission.Prelude import qualified Fission.Key.Symmetric.Types as Symmetric import Fission.User.DID.Types -newtype Store = Store { getStore :: DID :=> (FilePath :=> Symmetric.Key AES256) } +newtype Store = Store { getStore :: Map DID (Map FilePath (Symmetric.Key AES256)) } deriving newtype (Eq, ToJSON, FromJSON) - -type k :=> v = Map k v diff --git a/fission-cli/package.yaml b/fission-cli/package.yaml index 85f93a2e2..571829405 100644 --- a/fission-cli/package.yaml +++ b/fission-cli/package.yaml @@ -1,5 +1,5 @@ name: fission-cli -version: '2.11.1.0' +version: '2.12.0.0' category: CLI author: - Brooklyn Zelenka @@ -19,7 +19,7 @@ copyright: © 2021 Fission Internet Software Services for Open Networks Inc. license: AGPL-3.0-or-later license-file: LICENSE github: fission-suite/fission -tested-with: GHC==8.8.4 +tested-with: GHC==8.10.4 extra-source-files: - README.md diff --git a/fission-core/library/Fission/Key/Symmetric.hs b/fission-core/library/Fission/Key/Symmetric.hs index b5494d933..f56270eba 100644 --- a/fission-core/library/Fission/Key/Symmetric.hs +++ b/fission-core/library/Fission/Key/Symmetric.hs @@ -17,6 +17,8 @@ import Crypto.Cipher.Types import Crypto.Error import Crypto.Random.Types as Random +import Servant.API + import Fission.Prelude import Fission.Key.EncryptedWith.Types @@ -28,7 +30,7 @@ import Fission.Key.Symmetric.Types as Symmetric import Fission.Key.Symmetric.Types encrypt :: - ToJSON a + MimeRender OctetStream a => Symmetric.Key AES256 -> IV AES256 -> a @@ -45,9 +47,9 @@ encrypt (Symmetric.Key rawKey) iv plaintext = CryptoPassed blockCipher -> let - (authTag, cipherBS) = aeadSimpleEncrypt blockCipher ("" :: ByteString) (Lazy.toStrict $ encode plaintext) 16 + (authTag, cipherBS) = aeadSimpleEncrypt blockCipher ("" :: ByteString) (Lazy.toStrict $ mimeRender (Proxy @OctetStream) plaintext) 16 in - Right . EncryptedPayload $ Lazy.fromStrict (cipherBS <> (BA.convert authTag)) + Right . EncryptedPayload $ Lazy.fromStrict (cipherBS <> BA.convert authTag) decrypt :: Symmetric.Key AES256 @@ -66,7 +68,7 @@ decrypt (Symmetric.Key aesKey) iv (EncryptedPayload cipherLBS) = CryptoPassed blockCipher -> let - (cipherBS, tagBS) = BS.splitAt (fromIntegral $ (Lazy.length cipherLBS) - 16) (Lazy.toStrict cipherLBS) + (cipherBS, tagBS) = BS.splitAt (fromIntegral $ Lazy.length cipherLBS - 16) (Lazy.toStrict cipherLBS) authTag = AuthTag $ BA.convert tagBS mayClearBS = aeadSimpleDecrypt blockCipher ("" :: ByteString) cipherBS authTag in diff --git a/fission-core/library/Fission/Prelude.hs b/fission-core/library/Fission/Prelude.hs index 60018f8e4..f835511fe 100644 --- a/fission-core/library/Fission/Prelude.hs +++ b/fission-core/library/Fission/Prelude.hs @@ -38,6 +38,8 @@ module Fission.Prelude , module Test.QuickCheck , Entity (..) + , buildByteString + , buildLazyByteString , headMaybe , identity , intercalate @@ -70,7 +72,8 @@ import Control.Monad.Trans.Rescue import Network.IPFS.Internal.Orphanage.Utf8Builder () -import Data.Aeson hiding (Encoding, Options) +import Data.Aeson hiding (Encoding, + Options) import Data.Bifunctor (bimap) import Data.Bool import Data.Has hiding (Lens) @@ -107,11 +110,11 @@ import RIO hiding (Handler, (^.)) import Test.QuickCheck hiding - (Result (..)) + (Result (..)) import Test.QuickCheck.Instances () -import Fission.Unit.Prefix import Fission.Text.Encoded +import Fission.Unit.Prefix import Fission.Internal.Log @@ -124,6 +127,10 @@ import Fission.Internal.UTF8 (displayLazyBS, putTextLn, textShow) +-- Not reexported +import qualified Data.ByteString.Builder as Builder +import qualified RIO.ByteString.Lazy as Lazy + identity :: a -> a identity a = a @@ -135,3 +142,9 @@ ok = Right () noop :: Applicative f => f () noop = pure () + +buildByteString :: Utf8Builder -> ByteString +buildByteString utf8 = Lazy.toStrict $ buildLazyByteString utf8 + +buildLazyByteString :: Utf8Builder -> Lazy.ByteString +buildLazyByteString (Utf8Builder builder) = Builder.toLazyByteString builder diff --git a/fission-core/library/Fission/User/DID/Types.hs b/fission-core/library/Fission/User/DID/Types.hs index a3651ed6f..754daba83 100644 --- a/fission-core/library/Fission/User/DID/Types.hs +++ b/fission-core/library/Fission/User/DID/Types.hs @@ -7,9 +7,9 @@ module Fission.User.DID.Types import qualified Data.Aeson.Types as JSON import Data.Swagger -import qualified Data.ByteArray as BA import Data.Base58String.Bitcoin as BS58.BTC import Data.Binary hiding (encode) +import qualified Data.ByteArray as BA import qualified Data.ByteString.Base64 as BS64 import Data.Hashable (Hashable (..)) @@ -125,31 +125,7 @@ instance ToJSON DID where toJSON = String . textDisplay instance FromJSON DID where - parseJSON = withText "DID" \txt -> - case Text.stripPrefix "did:key:z" txt of - Nothing -> - fail $ show txt <> " does not have a valid did:key header" - - Just fragment -> do - pk <- case BS.unpack . BS58.BTC.toBytes $ BS58.BTC.fromText fragment of - (0xed : 0x01 : edKeyW8s) -> - if length edKeyW8s > 40 - then - -- Legacy encoding for backward compatability - Ed25519PublicKey <$> parseKeyW8s (BS.pack edKeyW8s) - - else - case Ed25519.publicKey $ BS.pack edKeyW8s of - CryptoFailed cryptoError -> fail $ "Unable to parse Ed25519 key: " <> show cryptoError - CryptoPassed edPK -> return $ Ed25519PublicKey edPK - - (0x00 : 0xF5 : 0x02 : rsaKeyW8s) -> - RSAPublicKey <$> parseKeyW8s (BS64.encode $ BS.pack rsaKeyW8s) - - nope -> - fail . show . BS64.encode $ BS.pack nope <> " is not an acceptable did:key" - - return $ DID Key pk + parseJSON = withText "DID" parseText instance Display (AlreadyExists DID) where display _ = "DID already exists / account already created" @@ -158,7 +134,34 @@ instance ToJSONKey DID where toJSONKey = JSON.toJSONKeyText textDisplay instance FromJSONKey DID where - fromJSONKey = FromJSONKeyValue parseJSON + fromJSONKey = FromJSONKeyTextParser parseText parseKeyW8s :: FromJSON a => ByteString -> JSON.Parser a parseKeyW8s = parseJSON . toJSON . decodeUtf8Lenient + +parseText :: Text -> JSON.Parser DID +parseText txt = + case Text.stripPrefix "did:key:z" txt of + Nothing -> + fail $ show txt <> " does not have a valid did:key header" + + Just fragment -> do + pk <- case BS.unpack . BS58.BTC.toBytes $ BS58.BTC.fromText fragment of + (0xed : 0x01 : edKeyW8s) -> + if length edKeyW8s > 40 + then + -- Legacy encoding for backward compatability + Ed25519PublicKey <$> parseKeyW8s (BS.pack edKeyW8s) + + else + case Ed25519.publicKey $ BS.pack edKeyW8s of + CryptoFailed cryptoError -> fail $ "Unable to parse Ed25519 key: " <> show cryptoError + CryptoPassed edPK -> return $ Ed25519PublicKey edPK + + (0x00 : 0xF5 : 0x02 : rsaKeyW8s) -> + RSAPublicKey <$> parseKeyW8s (BS64.encode $ BS.pack rsaKeyW8s) + + nope -> + fail . show . BS64.encode $ BS.pack nope <> " is not an acceptable did:key" + + return $ DID Key pk diff --git a/fission-core/library/Fission/Web/Auth/Token/Bearer/Types.hs b/fission-core/library/Fission/Web/Auth/Token/Bearer/Types.hs index bd1be17ec..1dd6135a8 100644 --- a/fission-core/library/Fission/Web/Auth/Token/Bearer/Types.hs +++ b/fission-core/library/Fission/Web/Auth/Token/Bearer/Types.hs @@ -4,13 +4,11 @@ module Fission.Web.Auth.Token.Bearer.Types , BareToken (..) ) where -import qualified Data.Binary.Builder as Builder - import qualified RIO.ByteString.Lazy as Lazy import qualified RIO.Text as Text -import Data.Swagger import Data.Aeson.Types +import Data.Swagger import Servant.API import Fission.Prelude @@ -38,7 +36,7 @@ instance Arbitrary Token where } instance Display Token where - textDisplay = Text.pack . show + textDisplay = toUrlPiece instance ToJSON Token where toJSON Token {jwt = JWT {sig}, rawContent} = @@ -77,6 +75,10 @@ instance FromHttpApiData Token where newtype BareToken = BareToken Token deriving (Eq, Show) +instance Display BareToken where + textDisplay (BareToken Token {jwt = JWT {sig}, rawContent}) = + utf8BuilderToText $ display rawContent <> "." <> display sig + instance ToJSON BareToken where toJSON (BareToken Token {jwt = JWT {sig}, rawContent}) = String $ textDisplay rawContent <> "." <> textDisplay sig @@ -88,11 +90,18 @@ instance FromJSON BareToken where instance MimeRender PlainText BareToken where mimeRender _ (BareToken Token {jwt = JWT {sig}, rawContent}) = - Builder.toLazyByteString . getUtf8Builder $ display rawContent <> "." <> display sig + buildLazyByteString $ display rawContent <> "." <> display sig + +instance MimeRender OctetStream BareToken where + mimeRender _ (BareToken Token {jwt = JWT {sig}, rawContent}) = + buildLazyByteString $ display rawContent <> "." <> display sig instance MimeUnrender PlainText BareToken where mimeUnrender _ lbs = eitherDecode ("\"" <> lbs <> "\"") +instance MimeUnrender OctetStream BareToken where + mimeUnrender _ lbs = eitherDecode ("\"" <> lbs <> "\"") + instance ToSchema BareToken where declareNamedSchema _ = mempty