[{"data":1,"prerenderedAt":1155},["ShallowReactive",2],{"\u002Farticles\u002Fabout":3,"sidebar-articles":79},{"id":4,"title":5,"author":6,"body":9,"date":70,"description":71,"extension":72,"image":8,"meta":73,"navigation":74,"path":75,"seo":76,"stem":77,"tags":8,"__hash__":78},"articles\u002Farticles\u002Fabout.md","About PlainKey",{"name":7,"avatar":8},"PlainKey",null,{"type":10,"value":11,"toc":65},"minimark",[12,16,19,22,25,28,33,44,47,50,52],[13,14,15],"p",{},"PlainKey started with a realisation in the spring of 2025. Adding passkeys to a web app means either using precious time building your own WebAuthn integration, or signing up for an enterprise auth platform. Those platforms often treat passkeys as one feature among dozens, and they can be costly. That is overkill when passkeys are all you need.",[13,17,18],{},"PlainKey also exists because Europe should have its own answers to tech infrastructure, and not wholly depend on US platforms. PlainKey is built in Norway and runs on servers in Germany, at Hetzner Online GmbH. Your users' data stays in the EU\u002FEEA.",[13,20,21],{},"For these reasons, we don't do enterprise features or pricing, and we are European-focused to the core. User data is never sold to third parties, and PlainKey will not add features that route authentication through platforms whose business depends on doing that.",[13,23,24],{},"While we have some ideas on how to expand beyond passkeys, for now passkeys are the focus. Whatever comes next will follow the same philosophy.",[26,27],"hr",{},[29,30,32],"h2",{"id":31},"who-is-behind-plainkey","Who is behind PlainKey?",[13,34,35,36,43],{},"PlainKey is built by ",[37,38,42],"a",{"href":39,"rel":40},"https:\u002F\u002Fsteen.cc",[41],"nofollow","Espen Steen",", a software developer based in Oslo, Norway.",[13,45,46],{},"Espen has 12+ years of experience as a CRM developer and consultant, having worked closely with some of Norway's largest and most well-known companies.",[13,48,49],{},"PlainKey AS is a publicly registered Norwegian limited company.",[26,51],{},[13,53,54,55,59,60,64],{},"Read the ",[37,56,58],{"href":57},"\u002Fdocs\u002Fgetting-started","getting started guide"," or ",[37,61,63],{"href":62},"\u002Farticles\u002Flearn-more","learn more about how PlainKey works",".",{"title":66,"searchDepth":67,"depth":67,"links":68},"",2,[69],{"id":31,"depth":67,"text":32},"28.04.2026","The story behind PlainKey and who built it.","md",{},true,"\u002Farticles\u002Fabout",{"title":5,"description":71},"articles\u002Fabout","OcJSaDqBjwa4a89fWFPCiGh6L6yMzIvg4S-lBe0einE",[80,118,435,618,978],{"id":4,"title":5,"author":81,"body":82,"date":70,"description":71,"extension":72,"image":8,"meta":116,"navigation":74,"path":75,"seo":117,"stem":77,"tags":8,"__hash__":78},{"name":7,"avatar":8},{"type":10,"value":83,"toc":113},[84,86,88,90,92,94,96,101,103,105,107],[13,85,15],{},[13,87,18],{},[13,89,21],{},[13,91,24],{},[26,93],{},[29,95,32],{"id":31},[13,97,35,98,43],{},[37,99,42],{"href":39,"rel":100},[41],[13,102,46],{},[13,104,49],{},[26,106],{},[13,108,54,109,59,111,64],{},[37,110,58],{"href":57},[37,112,63],{"href":62},{"title":66,"searchDepth":67,"depth":67,"links":114},[115],{"id":31,"depth":67,"text":32},{},{"title":5,"description":71},{"id":119,"title":120,"author":121,"body":122,"date":428,"description":429,"extension":72,"image":8,"meta":430,"navigation":74,"path":431,"seo":432,"stem":433,"tags":8,"__hash__":434},"articles\u002Farticles\u002Fhow-to-add-passkeys-to-your-website.md","How to add passkeys to your website",{"name":7,"avatar":8},{"type":10,"value":123,"toc":417},[124,127,130,132,136,139,142,145,158,161,163,167,170,173,176,179,181,185,192,195,220,225,320,323,327,358,365,369,372,380,382,386,389,392,395,397,401,413],[13,125,126],{},"Adding passkey authentication to a web app might sound straightforward until you start looking into it. The documentation you find is mostly aimed at people already familiar with browser security standards. Not exactly a smooth on-ramp when all you want to do is get passkeys working on your website.",[13,128,129],{},"This article is for developers who want to add passkeys without spending a week on the underlying cryptography. We will cover what passkeys are, why they are worth adding, and how to implement a working sign-up and sign-in flow using PlainKey.",[26,131],{},[29,133,135],{"id":134},"what-passkeys-are","What passkeys are",[13,137,138],{},"A passkey is a modern replacement for passwords. When a user registers with a passkey, their device generates a cryptographic key pair. The private key stays on the device and never leaves it. The public key is stored on your server. When the user wants to sign in, their device signs a challenge with the private key, and your server verifies it with the public key.",[13,140,141],{},"The user experience is simple: a fingerprint, a face scan, a PIN, or a hardware key like a YubiKey. No password to remember, no password to steal. Users tend to really like passkeys once they have registered one due to how frictionless it becomes.",[13,143,144],{},"A few things that make passkeys genuinely better than passwords:",[146,147,148,152,155],"ul",{},[149,150,151],"li",{},"They are phishing-resistant. Passkeys are bound to a specific domain and will not work on fake login pages.",[149,153,154],{},"Even if your server is breached, there are no passwords to steal. The private key never left the user's device.",[149,156,157],{},"They are an industry standard, supported across all modern browsers and platforms - Chrome, Safari, Firefox, iOS, Android, Windows.",[13,159,160],{},"Passkeys are built on the WebAuthn standard, which is what makes them work everywhere. WebAuthn is also what makes implementing them from scratch a significant project.",[26,162],{},[29,164,166],{"id":165},"what-raw-webauthn-implementation-involves","What raw WebAuthn implementation involves",[13,168,169],{},"If you are curious why passkey services exist, this section gives you a sense of what they abstract away. If you would rather just get started, skip ahead to the next section.",[13,171,172],{},"Implementing passkeys directly against the WebAuthn API means your backend needs to generate and manage cryptographic challenges, define registration options with the correct algorithm types and authenticator settings, and send all of that to the frontend in precisely the right format. Registration alone requires four API endpoints - two for sign-up, two for sign-in - with browser interaction happening between each pair of calls.",[13,174,175],{},"On the verification side, you are dealing with CBOR-encoded attestation objects, Base64 versus Base64URL encoding (a common source of errors), authenticator data parsing, relying party hash verification, and credential counter tracking. There are good open source libraries like SimpleWebAuthn that handle chunks of this, but you are still responsible for the integration, the credential storage schema, and understanding enough of the spec to debug it when something goes wrong.",[13,177,178],{},"It is doable. It is also a meaningful project before you have written a single line of your actual application.",[26,180],{},[29,182,184],{"id":183},"adding-passkeys-with-plainkey","Adding passkeys with PlainKey",[13,186,187,191],{},[37,188,7],{"href":189,"rel":190},"https:\u002F\u002Fplainkey.io",[41]," is a European-hosted passkey service that handles all of the above for you. The integration has two parts: a small JavaScript library (SDK) that goes in your frontend, and a token verification step in your backend. Both have been designed to be as simple to use as possible.",[13,193,194],{},"To install the PlainKey browser library, run the following in your project terminal:",[196,197,201],"pre",{"className":198,"code":199,"language":200,"meta":66,"style":66},"language-bash shiki shiki-themes github-light github-dark","npm install @plainkey\u002Fbrowser\n","bash",[202,203,204],"code",{"__ignoreMap":66},[205,206,209,213,217],"span",{"class":207,"line":208},"line",1,[205,210,212],{"class":211},"sScJk","npm",[205,214,216],{"class":215},"sZZnC"," install",[205,218,219],{"class":215}," @plainkey\u002Fbrowser\n",[221,222,224],"h3",{"id":223},"sign-up-registering-a-new-user-with-a-passkey","Sign up - registering a new user with a passkey",[196,226,230],{"className":227,"code":228,"language":229,"meta":66,"style":66},"language-ts shiki shiki-themes github-light github-dark","import { PlainKey } from \"@plainkey\u002Fbrowser\"\nconst plainKey = new PlainKey(\"YOUR_PROJECT_ID\")\n\nconst { data, error } = await plainKey.createUserWithPasskey(\"user@example.com\")\n","ts",[202,231,232,248,275,281],{"__ignoreMap":66},[205,233,234,238,242,245],{"class":207,"line":208},[205,235,237],{"class":236},"szBVR","import",[205,239,241],{"class":240},"sVt8B"," { PlainKey } ",[205,243,244],{"class":236},"from",[205,246,247],{"class":215}," \"@plainkey\u002Fbrowser\"\n",[205,249,250,253,257,260,263,266,269,272],{"class":207,"line":67},[205,251,252],{"class":236},"const",[205,254,256],{"class":255},"sj4cs"," plainKey",[205,258,259],{"class":236}," =",[205,261,262],{"class":236}," new",[205,264,265],{"class":211}," PlainKey",[205,267,268],{"class":240},"(",[205,270,271],{"class":215},"\"YOUR_PROJECT_ID\"",[205,273,274],{"class":240},")\n",[205,276,278],{"class":207,"line":277},3,[205,279,280],{"emptyLinePlaceholder":74},"\n",[205,282,284,286,289,292,295,298,301,304,307,310,313,315,318],{"class":207,"line":283},4,[205,285,252],{"class":236},[205,287,288],{"class":240}," { ",[205,290,291],{"class":255},"data",[205,293,294],{"class":240},", ",[205,296,297],{"class":255},"error",[205,299,300],{"class":240}," } ",[205,302,303],{"class":236},"=",[205,305,306],{"class":236}," await",[205,308,309],{"class":240}," plainKey.",[205,311,312],{"class":211},"createUserWithPasskey",[205,314,268],{"class":240},[205,316,317],{"class":215},"\"user@example.com\"",[205,319,274],{"class":240},[13,321,322],{},"That single call prompts the browser to create a passkey, registers the user in PlainKey, and returns an authentication token. The browser handles the key generation and the user interaction entirely.",[221,324,326],{"id":325},"sign-in-authenticating-an-existing-user","Sign in - authenticating an existing user",[196,328,330],{"className":227,"code":329,"language":229,"meta":66,"style":66},"const { data, error } = await plainKey.authenticate()\n",[202,331,332],{"__ignoreMap":66},[205,333,334,336,338,340,342,344,346,348,350,352,355],{"class":207,"line":208},[205,335,252],{"class":236},[205,337,288],{"class":240},[205,339,291],{"class":255},[205,341,294],{"class":240},[205,343,297],{"class":255},[205,345,300],{"class":240},[205,347,303],{"class":236},[205,349,306],{"class":236},[205,351,309],{"class":240},[205,353,354],{"class":211},"authenticate",[205,356,357],{"class":240},"()\n",[13,359,360,361,364],{},"Calling ",[202,362,363],{},".authenticate()"," without parameters prompts the user to pick from any passkey stored on their device for your domain. For most sign-in flows, that is exactly what you want.",[221,366,368],{"id":367},"the-backend-step","The backend step",[13,370,371],{},"Both calls return an authentication token. You pass that to your backend, where a single verification call to the PlainKey Server SDK or REST API returns the user's ID. You find or create that user in your own database, establish your session as you normally would, and you are done. Your user data stays in your own database throughout.",[13,373,374,375,64],{},"The full backend walkthrough is in the ",[37,376,379],{"href":377,"rel":378},"https:\u002F\u002Fplainkey.io\u002Fdocs",[41],"PlainKey docs",[26,381],{},[29,383,385],{"id":384},"what-plainkey-provides","What PlainKey provides",[13,387,388],{},"PlainKey handles the complex parts of passkey authentication: credential storage, challenge generation, signature verification, and the other details of WebAuthn. You use the PlainKey SDK and REST APIs to implement authentication on your site.",[13,390,391],{},"PlainKey stores the minimum amount of data about your users required for passkey management. You can even opt not to send any usernames or email addresses for your users at all.",[13,393,394],{},"What you handle: your app's UI, a few SDK calls, and your own user database and backend.",[26,396],{},[29,398,400],{"id":399},"getting-started","Getting started",[13,402,403,404,408,409,412],{},"Sign up at ",[37,405,407],{"href":189,"rel":406},[41],"plainkey.io",", create a project, and you will have a project ID within a minute. For local development, use ",[202,410,411],{},"localhost"," as your domain when creating the project.",[414,415,416],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":66,"searchDepth":67,"depth":67,"links":418},[419,420,421,426,427],{"id":134,"depth":67,"text":135},{"id":165,"depth":67,"text":166},{"id":183,"depth":67,"text":184,"children":422},[423,424,425],{"id":223,"depth":277,"text":224},{"id":325,"depth":277,"text":326},{"id":367,"depth":277,"text":368},{"id":384,"depth":67,"text":385},{"id":399,"depth":67,"text":400},"05.04.2026","How to add passwordless authentication to your web app without touching the WebAuthn spec",{},"\u002Farticles\u002Fhow-to-add-passkeys-to-your-website",{"title":120,"description":429},"articles\u002Fhow-to-add-passkeys-to-your-website","DcnUbb-b0JxBBVpWoi5jhapK-KcapP6jriefrHL8ugs",{"id":436,"title":437,"author":438,"body":439,"date":70,"description":613,"extension":72,"image":8,"meta":614,"navigation":74,"path":62,"seo":615,"stem":616,"tags":8,"__hash__":617},"articles\u002Farticles\u002Flearn-more.md","Passkeys and PlainKey",{"name":7,"avatar":8},{"type":10,"value":440,"toc":607},[441,447,449,453,456,459,462,468,470,474,477,480,482,486,497,500,503,572,575,578,583,585,589,592,594,604],[13,442,443,444,64],{},"PlainKey is a European passkey service built for developers who want to add passkeys without the complexity. If you want to know the full story, read the ",[37,445,446],{"href":75},"about page",[26,448],{},[29,450,452],{"id":451},"what-is-a-passkey","What is a passkey?",[13,454,455],{},"A passkey lets a user authenticate with a fingerprint, face scan, PIN, or security key. Users choose themselves how to store their passkey - like in a password manager of their choice or on a physical security key.",[13,457,458],{},"A passkey is bound to a specific domain, so phishing sites cannot use it. There are no passwords to steal if a server is breached.",[13,460,461],{},"Passkeys are built on WebAuthn, which all modern browsers and platforms support.",[463,464,465],"info",{},[13,466,467],{},"Passkeys work for sign-in, as a second factor (2FA\u002FMFA), or to verify a user before a sensitive action.",[26,469],{},[29,471,473],{"id":472},"implementing-webauthn-yourself","Implementing WebAuthn yourself",[13,475,476],{},"There are good open source libraries that handle the low-level cryptography, but there is still significant work around them. You need to manage short-lived challenges, persist credentials against your users, wire up registration and authentication flows, and handle browser compatibility edge cases. You should also understand the protocol well enough to use the library correctly and debug failures when they happen.",[13,478,479],{},"All this takes time you might want to spend on building your product instead. And getting any of this wrong can introduce security vulnerabilities.",[26,481],{},[29,483,485],{"id":484},"using-plainkey","Using PlainKey",[13,487,488,489,492,493,496],{},"You integrate with PlainKey via the npm package ",[202,490,491],{},"@plainkey\u002Fbrowser"," in the frontend, and the npm package ",[202,494,495],{},"@plainkey\u002Fserver"," in your backend. If you do not use Node.js for your backend, you can also call the REST API from your backend.",[13,498,499],{},"The APIs and SDKs are designed with two main goals in mind: simplicity and security.",[13,501,502],{},"The docs cover the full integration in more detail. Browser-side, authenticating a user essentially looks like this:",[196,504,508],{"className":505,"code":506,"language":507,"meta":66,"style":66},"language-typescript shiki shiki-themes github-light github-dark","import { PlainKey } from \"@plainkey\u002Fbrowser\";\n\nconst plainKey = new PlainKey(\"YOUR_PROJECT_ID\");\nconst { data, error } = await plainKey.authenticate();\n","typescript",[202,509,510,524,528,547],{"__ignoreMap":66},[205,511,512,514,516,518,521],{"class":207,"line":208},[205,513,237],{"class":236},[205,515,241],{"class":240},[205,517,244],{"class":236},[205,519,520],{"class":215}," \"@plainkey\u002Fbrowser\"",[205,522,523],{"class":240},";\n",[205,525,526],{"class":207,"line":67},[205,527,280],{"emptyLinePlaceholder":74},[205,529,530,532,534,536,538,540,542,544],{"class":207,"line":277},[205,531,252],{"class":236},[205,533,256],{"class":255},[205,535,259],{"class":236},[205,537,262],{"class":236},[205,539,265],{"class":211},[205,541,268],{"class":240},[205,543,271],{"class":215},[205,545,546],{"class":240},");\n",[205,548,549,551,553,555,557,559,561,563,565,567,569],{"class":207,"line":283},[205,550,252],{"class":236},[205,552,288],{"class":240},[205,554,291],{"class":255},[205,556,294],{"class":240},[205,558,297],{"class":255},[205,560,300],{"class":240},[205,562,303],{"class":236},[205,564,306],{"class":236},[205,566,309],{"class":240},[205,568,354],{"class":211},[205,570,571],{"class":240},"();\n",[13,573,574],{},"You can use PlainKey as your primary authentication or add it to an existing auth system. Either way, it does not replace your user database or session handling. You receive a signed authentication token; your server verifies it with the server SDK or API and creates a session as normal.",[13,576,577],{},"PlainKey handles credential storage, challenge generation, signature verification, key management, and authenticator metadata, and provides you with an admin dashboard. You handle your UI, a few SDK calls or API requests, and your own user and session logic.",[463,579,580],{},[13,581,582],{},"PlainKey stores only the data required for passkey management. You can even opt not to send usernames or email addresses to PlainKey at all.",[26,584],{},[29,586,588],{"id":587},"what-if-i-use-plainkey-for-a-while-and-then-want-to-migrate-to-my-own-infrastructure","What if I use PlainKey for a while and then want to migrate to my own infrastructure?",[13,590,591],{},"You can. The passkeys created using PlainKey are scoped to your domain, meaning they will work just fine no matter where the credential data is stored. If you decide to leave, contact support and PlainKey will export all the necessary data. A fee may apply. Identity verification is required before any export. The credential data is yours to keep, but you would be taking on the implementation work.",[26,593],{},[13,595,54,596,598,599,64],{},[37,597,58],{"href":57}," or try the ",[37,600,603],{"href":601,"rel":602},"https:\u002F\u002Fdemo.plainkey.io",[41],"demo",[414,605,606],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":66,"searchDepth":67,"depth":67,"links":608},[609,610,611,612],{"id":451,"depth":67,"text":452},{"id":472,"depth":67,"text":473},{"id":484,"depth":67,"text":485},{"id":587,"depth":67,"text":588},"What passkeys are and how PlainKey handles them for you.",{},{"title":437,"description":613},"articles\u002Flearn-more","Qhy8E5fpSe6QzkLp9hw_VjIJlOgxdbkB6XXQOgfrpuA",{"id":619,"title":620,"author":621,"body":622,"date":70,"description":972,"extension":72,"image":8,"meta":973,"navigation":74,"path":974,"seo":975,"stem":976,"tags":8,"__hash__":977},"articles\u002Farticles\u002Fprivacy.md","Privacy Policy",{"name":7,"avatar":8},{"type":10,"value":623,"toc":957},[624,638,641,644,646,650,672,675,682,684,688,691,695,702,705,728,731,733,737,743,746,759,762,773,775,782,784,788,791,808,811,813,817,820,840,842,846,849,852,854,858,861,872,874,878,881,895,898,900,904,909,911,915,918,938,945,948,950,954],[13,625,626,627,630,631,630,634,637],{},"PlainKey AS (NO 937 528 779) (\"",[628,629,7],"strong",{},"\", \"",[628,632,633],{},"we",[628,635,636],{},"us","\") provides a passkeys-only authentication service for developers and organisations.",[13,639,640],{},"This Privacy Policy explains what personal data we process, why we process it, and your rights under the General Data Protection Regulation (\"GDPR\") and the Norwegian Personal Data Act (LOV-2018-06-15-38).",[13,642,643],{},"PlainKey is designed as a European-first authentication service, with GDPR considerations built into the architecture from the start. We aim to minimise personal data, clearly separate data controller and processor roles, and provide transparency around how data is handled.",[26,645],{},[29,647,649],{"id":648},"_1-who-we-are","1. Who we are",[13,651,652,655,656,659,660,663,664,667,668],{},[628,653,654],{},"Service name:"," PlainKey\n",[628,657,658],{},"Operator:"," PlainKey AS (NO 937 528 779)\n",[628,661,662],{},"Location:"," Norway\n",[628,665,666],{},"Contact:"," ",[37,669,671],{"href":670},"mailto:privacy@plainkey.io","privacy@plainkey.io",[13,673,674],{},"PlainKey is the data controller for personal data processed in connection with our website and customer accounts.",[13,676,677,678,681],{},"When PlainKey is used by customers to authenticate their own end users, PlainKey acts as a ",[628,679,680],{},"data processor"," on behalf of the customer.",[26,683],{},[29,685,687],{"id":686},"_2-data-roles-and-responsibilities","2. Data roles and responsibilities",[13,689,690],{},"PlainKey processes personal data in two distinct contexts:",[221,692,694],{"id":693},"_21-plainkey-customers-account-holders","2.1 PlainKey customers (account holders)",[13,696,697,698,701],{},"When individuals or organisations create an account with PlainKey, PlainKey acts as the ",[628,699,700],{},"data controller"," for personal data related to those customer accounts.",[13,703,704],{},"This includes data such as:",[146,706,707,710,713,716,719,722,725],{},[149,708,709],{},"name",[149,711,712],{},"email address",[149,714,715],{},"company information",[149,717,718],{},"authenticator metadata required for authentication security",[149,720,721],{},"public key credential data (WebAuthn credentials), authentication challenges, and other data used for authentication",[149,723,724],{},"authentication event data, including IP address and User-Agent (device) data",[149,726,727],{},"account and project metadata",[13,729,730],{},"This data is processed to provide, operate, and secure the PlainKey service.",[26,732],{},[221,734,736],{"id":735},"_22-end-users-of-plainkey-customers","2.2 End users of PlainKey customers",[13,738,739,740,64],{},"When PlainKey is used to enable passkey authentication for a customer's application, PlainKey processes authentication data ",[628,741,742],{},"on behalf of the customer",[13,744,745],{},"In this context:",[146,747,748,754],{},[149,749,750,751],{},"the ",[628,752,753],{},"customer is the data controller",[149,755,756],{},[628,757,758],{},"PlainKey acts as a data processor",[13,760,761],{},"PlainKey processes only the data required to perform authentication, such as:",[146,763,764,767,769,771],{},[149,765,766],{},"user identifiers (e.g. username or email, as provided by the customer)",[149,768,721],{},[149,770,718],{},[149,772,724],{},[13,774,730],{},[13,776,777,778,781],{},"PlainKey does ",[628,779,780],{},"not"," manage end-user identities, user profiles, or application sessions. Customers remain fully responsible for identity management, session handling, and communication with their end users.",[26,783],{},[29,785,787],{"id":786},"_3-what-data-we-do-not-process","3. What data we do not process",[13,789,790],{},"PlainKey does not:",[146,792,793,796,799,802,805],{},[149,794,795],{},"store passwords",[149,797,798],{},"store private cryptographic keys",[149,800,801],{},"sell personal data",[149,803,804],{},"use personal data for advertising",[149,806,807],{},"track end users across unrelated websites",[13,809,810],{},"Private authentication keys remain securely on the user's device or platform authenticator.",[26,812],{},[29,814,816],{"id":815},"_4-legal-basis-for-processing","4. Legal basis for processing",[13,818,819],{},"PlainKey processes personal data under the following GDPR legal bases:",[146,821,822,828,834],{},[149,823,824,827],{},[628,825,826],{},"Contract - Article 6(1)(b)"," - to provide and operate the PlainKey service (contractual obligations between PlainKey and its customers)",[149,829,830,833],{},[628,831,832],{},"Legitimate interests - Article 6(1)(f)"," - to maintain security, prevent abuse, and improve reliability (to protect the security and integrity of the PlainKey service)",[149,835,836,839],{},[628,837,838],{},"Legal obligations - Article 6(1)(c)"," - where required by applicable law (to comply with legal obligations such as data protection laws)",[26,841],{},[29,843,845],{"id":844},"_5-international-data-transfers","5. International data transfers",[13,847,848],{},"PlainKey follows a Europe-first infrastructure approach. We prioritise EU regions and GDPR safeguards when selecting infrastructure providers. Personal data is currently stored and processed on servers located in Germany, hosted by Hetzner Online GmbH, an EU-based provider.",[13,850,851],{},"If personal data is ever transferred outside the EEA, appropriate safeguards (such as Standard Contractual Clauses) will be applied in accordance with GDPR requirements.",[26,853],{},[29,855,857],{"id":856},"_6-data-retention","6. Data retention",[13,859,860],{},"PlainKey retains personal data only for as long as necessary:",[146,862,863,866,869],{},[149,864,865],{},"customer account data is retained until deletion is requested or required for legal reasons",[149,867,868],{},"authentication credential data is retained while the customer uses the service",[149,870,871],{},"logs are retained for a limited period for security, debugging, and abuse prevention",[26,873],{},[29,875,877],{"id":876},"_7-security-measures","7. Security measures",[13,879,880],{},"PlainKey implements appropriate technical and organisational measures to protect personal data, including:",[146,882,883,886,889,892],{},[149,884,885],{},"encryption in transit (TLS)",[149,887,888],{},"authenticated and restricted access to production systems",[149,890,891],{},"least-privilege access principles",[149,893,894],{},"logging and monitoring for security and abuse prevention",[13,896,897],{},"Security practices are continuously reviewed and improved as the service evolves.",[26,899],{},[29,901,903],{"id":902},"_8-data-processing-agreement-dpa","8. Data Processing Agreement (DPA)",[13,905,906,907,64],{},"When acting as a data processor for customer end users, PlainKey provides a Data Processing Agreement (DPA) upon request. Contact us at ",[37,908,671],{"href":670},[26,910],{},[29,912,914],{"id":913},"_9-your-rights","9. Your rights",[13,916,917],{},"Under the GDPR and the Norwegian Personal Data Act, individuals have the right to:",[146,919,920,923,926,929,932,935],{},[149,921,922],{},"access their personal data",[149,924,925],{},"request correction or deletion",[149,927,928],{},"object to processing",[149,930,931],{},"request restriction of processing",[149,933,934],{},"data portability",[149,936,937],{},"lodge a complaint with a supervisory authority",[13,939,940,941,64],{},"Requests may be sent to ",[628,942,943],{},[37,944,671],{"href":670},[13,946,947],{},"Where PlainKey acts as a data processor, end users should generally direct privacy-related requests to the relevant customer, who acts as the data controller for that data.",[26,949],{},[29,951,953],{"id":952},"_10-changes-to-this-policy","10. Changes to this policy",[13,955,956],{},"We reserve the right to update this Privacy Policy as PlainKey evolves.\nThe most recent version will always be available on this page.",{"title":66,"searchDepth":67,"depth":67,"links":958},[959,960,964,965,966,967,968,969,970,971],{"id":648,"depth":67,"text":649},{"id":686,"depth":67,"text":687,"children":961},[962,963],{"id":693,"depth":277,"text":694},{"id":735,"depth":277,"text":736},{"id":786,"depth":67,"text":787},{"id":815,"depth":67,"text":816},{"id":844,"depth":67,"text":845},{"id":856,"depth":67,"text":857},{"id":876,"depth":67,"text":877},{"id":902,"depth":67,"text":903},{"id":913,"depth":67,"text":914},{"id":952,"depth":67,"text":953},"This Privacy Policy document explains what personal data we process, why we process it, and your rights under the General Data Protection Regulation (\"GDPR\").",{"version":208},"\u002Farticles\u002Fprivacy",{"title":620,"description":972},"articles\u002Fprivacy","2M1aQ1XfqDRWQZykykBCfBwRLe14g_O3P6p7uOW9qkM",{"id":979,"title":980,"author":981,"body":982,"date":70,"description":1149,"extension":72,"image":8,"meta":1150,"navigation":74,"path":1151,"seo":1152,"stem":1153,"tags":8,"__hash__":1154},"articles\u002Farticles\u002Fterms.md","Terms of Use",{"name":7,"avatar":8},{"type":10,"value":983,"toc":1136},[984,987,990,992,996,999,1002,1013,1015,1019,1022,1030,1032,1036,1039,1042,1045,1047,1051,1054,1057,1059,1063,1066,1071,1073,1077,1082,1084,1088,1093,1096,1098,1102,1105,1107,1111,1114,1116,1120,1123,1125,1129,1132],[13,985,986],{},"These Terms of Use (\"Terms\") govern access to and use of PlainKey AS (NO 937 528 779) (\"PlainKey\", \"we\", \"us\"), a passkeys-only authentication service.",[13,988,989],{},"By creating an account or using the service, you agree to these Terms.",[26,991],{},[29,993,995],{"id":994},"_1-use-of-the-service","1. Use of the service",[13,997,998],{},"You agree to use PlainKey only for lawful purposes and in accordance with these Terms.",[13,1000,1001],{},"You must not:",[146,1003,1004,1007,1010],{},[149,1005,1006],{},"attempt to gain unauthorised access to the service or its systems",[149,1008,1009],{},"interfere with or disrupt the service",[149,1011,1012],{},"use the service in a way that violates applicable laws or regulations",[26,1014],{},[29,1016,1018],{"id":1017},"_2-accounts-and-security","2. Accounts and security",[13,1020,1021],{},"You are responsible for maintaining the security of your account and for all activity carried out under it.",[13,1023,1024,1025,1029],{},"If you believe your account has been compromised, notify us at ",[37,1026,1028],{"href":1027},"mailto:hello@plainkey.io","hello@plainkey.io"," as soon as possible.",[26,1031],{},[29,1033,1035],{"id":1034},"_3-availability","3. Availability",[13,1037,1038],{},"The service is provided on an \"as is\" and \"as available\" basis. PlainKey gives no warranty, express or implied, that the service will be error-free or uninterrupted.",[13,1040,1041],{},"PlainKey provides authentication infrastructure and APIs. Customers are responsible for implementing and configuring the service correctly within their own applications. PlainKey does not control how customers integrate the service, manage user sessions, or authorise access within their systems.",[13,1043,1044],{},"Customers remain responsible for the security of their applications, and for ensuring that their use of PlainKey meets their own security and compliance requirements.",[26,1046],{},[29,1048,1050],{"id":1049},"_4-limitation-of-liability","4. Limitation of liability",[13,1052,1053],{},"In the event of a liability claim, total damages are limited to 50% of the fees the customer has paid in the preceding 12 months. These limitations do not apply if the breaching party has exhibited gross negligence or wilful misconduct.",[13,1055,1056],{},"PlainKey is not liable for indirect or consequential damages, including loss of profit, loss of data, or loss of goodwill.",[26,1058],{},[29,1060,1062],{"id":1061},"_5-suspension-and-termination","5. Suspension and termination",[13,1064,1065],{},"We may suspend or terminate access to the service in cases of misuse, security concerns, or violations of these Terms.",[13,1067,1068,1069,64],{},"You may stop using the service at any time. To delete your account and associated data, contact us at ",[37,1070,1028],{"href":1027},[26,1072],{},[29,1074,1076],{"id":1075},"_6-data-portability","6. Data portability",[13,1078,1079,1080,64],{},"You may request an export of your data at any time by contacting ",[37,1081,1028],{"href":1027},[26,1083],{},[29,1085,1087],{"id":1086},"_7-privacy-and-data-protection","7. Privacy and data protection",[13,1089,1090,1091,64],{},"Our processing of personal data is described in our ",[628,1092,620],{},[13,1094,1095],{},"Where PlainKey processes personal data on behalf of customers, customers remain responsible for ensuring appropriate notices and legal bases for their end users.",[26,1097],{},[29,1099,1101],{"id":1100},"_8-pricing","8. Pricing",[13,1103,1104],{},"We reserve the right to change our pricing. We will provide at least 30 days' notice of any price changes via email. If you do not agree to the new pricing, you may terminate your subscription before the changes take effect.",[26,1106],{},[29,1108,1110],{"id":1109},"_9-changes-to-these-terms","9. Changes to these Terms",[13,1112,1113],{},"We may update these Terms as the service evolves. The most recent version will always be available on this page. Continued use of the service after changes constitutes acceptance of the updated Terms.",[26,1115],{},[29,1117,1119],{"id":1118},"_10-governing-law-and-disputes","10. Governing law and disputes",[13,1121,1122],{},"These Terms are governed by Norwegian law.",[26,1124],{},[29,1126,1128],{"id":1127},"_11-contact","11. Contact",[13,1130,1131],{},"If you have questions about these Terms, contact us at:",[13,1133,1134],{},[37,1135,1028],{"href":1027},{"title":66,"searchDepth":67,"depth":67,"links":1137},[1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148],{"id":994,"depth":67,"text":995},{"id":1017,"depth":67,"text":1018},{"id":1034,"depth":67,"text":1035},{"id":1049,"depth":67,"text":1050},{"id":1061,"depth":67,"text":1062},{"id":1075,"depth":67,"text":1076},{"id":1086,"depth":67,"text":1087},{"id":1100,"depth":67,"text":1101},{"id":1109,"depth":67,"text":1110},{"id":1118,"depth":67,"text":1119},{"id":1127,"depth":67,"text":1128},"This document explains the terms and conditions for using PlainKey.",{"version":208},"\u002Farticles\u002Fterms",{"title":980,"description":1149},"articles\u002Fterms","MXAj7uFp_RiDAEbSujvDRiPds9EKuJs9ukceFtn3MOo",1777837159516]