[{"data":1,"prerenderedAt":1801},["ShallowReactive",2],{"\u002Farticles\u002Fprivacy":3,"sidebar-articles":381},{"id":4,"title":5,"author":6,"body":9,"date":371,"description":372,"extension":373,"image":8,"meta":374,"navigation":376,"path":377,"seo":378,"stem":379,"tags":8,"__hash__":380},"articles\u002Farticles\u002Fprivacy.md","Privacy Policy",{"name":7,"avatar":8},"PlainKey",null,{"type":10,"value":11,"toc":353},"minimark",[12,27,30,33,36,41,64,67,74,76,80,83,88,95,98,123,126,128,132,139,142,155,158,169,171,178,180,184,187,204,207,209,213,216,236,238,242,245,248,250,254,257,268,270,274,277,291,294,296,300,305,307,311,314,334,341,344,346,350],[13,14,15,16,19,20,19,23,26],"p",{},"PlainKey AS (NO 937 528 779) (\"",[17,18,7],"strong",{},"\", \"",[17,21,22],{},"we",[17,24,25],{},"us","\") provides a passkeys-only authentication service for developers and organisations.",[13,28,29],{},"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,31,32],{},"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.",[34,35],"hr",{},[37,38,40],"h2",{"id":39},"_1-who-we-are","1. Who we are",[13,42,43,46,47,50,51,54,55,58,59],{},[17,44,45],{},"Service name:"," PlainKey\n",[17,48,49],{},"Operator:"," PlainKey AS (NO 937 528 779)\n",[17,52,53],{},"Location:"," Norway\n",[17,56,57],{},"Contact:"," ",[60,61,63],"a",{"href":62},"mailto:privacy@plainkey.io","privacy@plainkey.io",[13,65,66],{},"PlainKey is the data controller for personal data processed in connection with our website and customer accounts.",[13,68,69,70,73],{},"When PlainKey is used by customers to authenticate their own end users, PlainKey acts as a ",[17,71,72],{},"data processor"," on behalf of the customer.",[34,75],{},[37,77,79],{"id":78},"_2-data-roles-and-responsibilities","2. Data roles and responsibilities",[13,81,82],{},"PlainKey processes personal data in two distinct contexts:",[84,85,87],"h3",{"id":86},"_21-plainkey-customers-account-holders","2.1 PlainKey customers (account holders)",[13,89,90,91,94],{},"When individuals or organisations create an account with PlainKey, PlainKey acts as the ",[17,92,93],{},"data controller"," for personal data related to those customer accounts.",[13,96,97],{},"This includes data such as:",[99,100,101,105,108,111,114,117,120],"ul",{},[102,103,104],"li",{},"name",[102,106,107],{},"email address",[102,109,110],{},"company information",[102,112,113],{},"authenticator metadata required for authentication security",[102,115,116],{},"public key credential data (WebAuthn credentials), authentication challenges, and other data used for authentication",[102,118,119],{},"authentication event data, including IP address and User-Agent (device) data",[102,121,122],{},"account and project metadata",[13,124,125],{},"This data is processed to provide, operate, and secure the PlainKey service.",[34,127],{},[84,129,131],{"id":130},"_22-end-users-of-plainkey-customers","2.2 End users of PlainKey customers",[13,133,134,135,138],{},"When PlainKey is used to enable passkey authentication for a customer's application, PlainKey processes authentication data ",[17,136,137],{},"on behalf of the customer",".",[13,140,141],{},"In this context:",[99,143,144,150],{},[102,145,146,147],{},"the ",[17,148,149],{},"customer is the data controller",[102,151,152],{},[17,153,154],{},"PlainKey acts as a data processor",[13,156,157],{},"PlainKey processes only the data required to perform authentication, such as:",[99,159,160,163,165,167],{},[102,161,162],{},"user identifiers (e.g. username or email, as provided by the customer)",[102,164,116],{},[102,166,113],{},[102,168,119],{},[13,170,125],{},[13,172,173,174,177],{},"PlainKey does ",[17,175,176],{},"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.",[34,179],{},[37,181,183],{"id":182},"_3-what-data-we-do-not-process","3. What data we do not process",[13,185,186],{},"PlainKey does not:",[99,188,189,192,195,198,201],{},[102,190,191],{},"store passwords",[102,193,194],{},"store private cryptographic keys",[102,196,197],{},"sell personal data",[102,199,200],{},"use personal data for advertising",[102,202,203],{},"track end users across unrelated websites",[13,205,206],{},"Private authentication keys remain securely on the user's device or platform authenticator.",[34,208],{},[37,210,212],{"id":211},"_4-legal-basis-for-processing","4. Legal basis for processing",[13,214,215],{},"PlainKey processes personal data under the following GDPR legal bases:",[99,217,218,224,230],{},[102,219,220,223],{},[17,221,222],{},"Contract - Article 6(1)(b)"," - to provide and operate the PlainKey service (contractual obligations between PlainKey and its customers)",[102,225,226,229],{},[17,227,228],{},"Legitimate interests - Article 6(1)(f)"," - to maintain security, prevent abuse, and improve reliability (to protect the security and integrity of the PlainKey service)",[102,231,232,235],{},[17,233,234],{},"Legal obligations - Article 6(1)(c)"," - where required by applicable law (to comply with legal obligations such as data protection laws)",[34,237],{},[37,239,241],{"id":240},"_5-international-data-transfers","5. International data transfers",[13,243,244],{},"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,246,247],{},"If personal data is ever transferred outside the EEA, appropriate safeguards (such as Standard Contractual Clauses) will be applied in accordance with GDPR requirements.",[34,249],{},[37,251,253],{"id":252},"_6-data-retention","6. Data retention",[13,255,256],{},"PlainKey retains personal data only for as long as necessary:",[99,258,259,262,265],{},[102,260,261],{},"customer account data is retained until deletion is requested or required for legal reasons",[102,263,264],{},"authentication credential data is retained while the customer uses the service",[102,266,267],{},"logs are retained for a limited period for security, debugging, and abuse prevention",[34,269],{},[37,271,273],{"id":272},"_7-security-measures","7. Security measures",[13,275,276],{},"PlainKey implements appropriate technical and organisational measures to protect personal data, including:",[99,278,279,282,285,288],{},[102,280,281],{},"encryption in transit (TLS)",[102,283,284],{},"authenticated and restricted access to production systems",[102,286,287],{},"least-privilege access principles",[102,289,290],{},"logging and monitoring for security and abuse prevention",[13,292,293],{},"Security practices are continuously reviewed and improved as the service evolves.",[34,295],{},[37,297,299],{"id":298},"_8-data-processing-agreement-dpa","8. Data Processing Agreement (DPA)",[13,301,302,303,138],{},"When acting as a data processor for customer end users, PlainKey provides a Data Processing Agreement (DPA) upon request. Contact us at ",[60,304,63],{"href":62},[34,306],{},[37,308,310],{"id":309},"_9-your-rights","9. Your rights",[13,312,313],{},"Under the GDPR and the Norwegian Personal Data Act, individuals have the right to:",[99,315,316,319,322,325,328,331],{},[102,317,318],{},"access their personal data",[102,320,321],{},"request correction or deletion",[102,323,324],{},"object to processing",[102,326,327],{},"request restriction of processing",[102,329,330],{},"data portability",[102,332,333],{},"lodge a complaint with a supervisory authority",[13,335,336,337,138],{},"Requests may be sent to ",[17,338,339],{},[60,340,63],{"href":62},[13,342,343],{},"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.",[34,345],{},[37,347,349],{"id":348},"_10-changes-to-this-policy","10. Changes to this policy",[13,351,352],{},"We reserve the right to update this Privacy Policy as PlainKey evolves.\nThe most recent version will always be available on this page.",{"title":354,"searchDepth":355,"depth":355,"links":356},"",2,[357,358,363,364,365,366,367,368,369,370],{"id":39,"depth":355,"text":40},{"id":78,"depth":355,"text":79,"children":359},[360,362],{"id":86,"depth":361,"text":87},3,{"id":130,"depth":361,"text":131},{"id":182,"depth":355,"text":183},{"id":211,"depth":355,"text":212},{"id":240,"depth":355,"text":241},{"id":252,"depth":355,"text":253},{"id":272,"depth":355,"text":273},{"id":298,"depth":355,"text":299},{"id":309,"depth":355,"text":310},{"id":348,"depth":355,"text":349},"28.04.2026","This Privacy Policy document explains what personal data we process, why we process it, and your rights under the General Data Protection Regulation (\"GDPR\").","md",{"version":375},1,true,"\u002Farticles\u002Fprivacy",{"title":5,"description":372},"articles\u002Fprivacy","2M1aQ1XfqDRWQZykykBCfBwRLe14g_O3P6p7uOW9qkM",[382,468,838,899,1195,1377,1624],{"id":383,"title":384,"author":385,"body":387,"date":461,"description":462,"extension":373,"image":8,"meta":463,"navigation":376,"path":464,"seo":465,"stem":466,"tags":8,"__hash__":467},"articles\u002Farticles\u002Fa-quick-terminology-guide.md","A quick passkey terminology guide: FIDO2, WebAuthn, passkeys, and security keys",{"name":386,"avatar":8},"Espen Steen",{"type":10,"value":388,"toc":458},[389,392,394,405,407,413,415,430,432,438,440,446,449,451,455],[13,390,391],{},"FIDO, FIDO2, WebAuthn, passkeys, and security keys are all related but distinct terms. These terms get used interchangeably, and often in the wrong context. Frankly, the naming around passkeys is a bit of a mess. The terms come from different places: a standards body, a web standards organisation, and consumer-facing marketing from platform vendors. That's why they don't map onto each other cleanly, and it leaves the people who just want passkeys on their site confused. Don't feel bad, you're not alone, and here is a quick guide to help you understand what each term means.",[34,393],{},[13,395,396,399,400,404],{},[17,397,398],{},"The FIDO Alliance"," is the industry consortium behind the standards. It was founded in July 2012 by PayPal, Lenovo, Nok Nok Labs, Validity Sensors, Infineon, and Agnitio; Google, Yubico, and others joined in 2013. FIDO stands for Fast IDentity Online, a name that also nods to the Latin ",[401,402,403],"em",{},"fidus"," (faithful, trustworthy), the same root as the dog name Fido. The Alliance publishes specifications and certifies devices. It's not a product or protocol; it's the organisation that created everything else on this list.",[34,406],{},[13,408,409,412],{},[17,410,411],{},"FIDO2"," is the current generation of FIDO standards, published in 2018. It covers both the browser API (WebAuthn) and the protocol for communicating with hardware authenticators. When someone says a site \"supports FIDO2\", they mean it can accept credentials created via this standard.",[34,414],{},[13,416,417,420,421,425,426,429],{},[17,418,419],{},"WebAuthn"," is the browser-facing part of FIDO2, written by the W3C. It defines the JavaScript API (",[422,423,424],"code",{},"navigator.credentials.create()"," and ",[422,427,428],{},"navigator.credentials.get()",") that web apps use to register and verify credentials. If you're implementing passkey auth in a web app, WebAuthn is what you're coding against.",[34,431],{},[13,433,434,437],{},[17,435,436],{},"Security key"," is a hardware device that generates and stores cryptographic key pairs on-device. The private key never leaves the hardware. Depending on how a site is configured, they can function as a second factor or as a passwordless credential. People often use \"YubiKey\" as shorthand for any security key, but YubiKey is a product made by Yubico; other brands exist, like Google's Titan Security Key.",[34,439],{},[13,441,442,445],{},[17,443,444],{},"Passkey"," is the name for a credential that lets you authenticate without a password. It uses FIDO2 as the underlying standard, and WebAuthn to interact with the browser. The term was introduced in 2022 by Apple, Google, and Microsoft and adopted by the FIDO Alliance as the common consumer-facing name for this kind of credential.",[13,447,448],{},"A passkey can be stored in several places: a platform credential manager like iCloud Keychain, Google Password Manager, or Windows Hello; a third-party password manager like 1Password or Bitwarden; or a physical hardware security key. The credential works the same way regardless of where it lives; the difference is portability. A passkey in iCloud Keychain is available on all your Apple devices. A passkey on a hardware key stays on that device.",[34,450],{},[37,452,454],{"id":453},"adding-passkeys-to-your-app","Adding passkeys to your app",[13,456,457],{},"Implementing WebAuthn from scratch involves credential storage, challenge generation, signature verification, and more. Several services exist to handle this for you. PlainKey is one of them: it stores passkeys, manages the cryptographic plumbing, and exposes a simple API so you can add passkey support to your app without building or maintaining the underlying infrastructure yourself.",{"title":354,"searchDepth":355,"depth":355,"links":459},[460],{"id":453,"depth":355,"text":454},"13.06.2026","A plain explanation of how FIDO2, WebAuthn, passkeys, and security keys relate to each other.",{},"\u002Farticles\u002Fa-quick-terminology-guide",{"title":384,"description":462},"articles\u002Fa-quick-terminology-guide","Mp21ShQxV0FswYJf9RTjdjGbXo0rZQ0fm3ODEqaJatM",{"id":469,"title":470,"author":471,"body":472,"date":461,"description":832,"extension":373,"image":8,"meta":833,"navigation":376,"path":834,"seo":835,"stem":836,"tags":8,"__hash__":837},"articles\u002Farticles\u002Faaguids-and-passkey-authenticator-types.md","AAGUIDs and how to identify what type of authenticator a passkey was created with",{"name":386,"avatar":8},{"type":10,"value":473,"toc":825},[474,477,480,489,492,495,497,501,504,507,510,519,528,530,534,540,550,553,674,677,679,683,686,692,698,704,706,710,713,716,719,722,797,807,809,813,821],[13,475,476],{},"Every time a user registers a passkey, something travels along with the passkey registration that is quite useful: a UUID that identifies exactly which type of password manager or security device created the credential.",[13,478,479],{},"That UUID is called an AAGUID. Here is what one looks like:",[481,482,487],"pre",{"className":483,"code":485,"language":486},[484],"language-text","fbfc3007-154e-4ecc-8c0b-6e020557d7bd\n","text",[422,488,485],{"__ignoreMap":354},[13,490,491],{},"This particular AAGUID means Apple Passwords, the password manager built into iPhone, iPad, and Mac. A different AAGUID would tell you it was, for example, a YubiKey, or Google Password Manager, Windows Hello or Proton Pass. The AAGUID travels with every passkey registration, and with the right lookup table, it turns a meaningless UUID into a human-readable name.",[13,493,494],{},"Let's jump into the details. Why they're useful, the great open source library that maps them to names, and how PlainKey uses them so your users get automatic, readable passkey labels without you writing any extra code.",[34,496],{},[37,498,500],{"id":499},"what-an-aaguid-is","What an AAGUID is",[13,502,503],{},"AAGUID stands for Authenticator Attestation GUID. \"Authenticator\" is the term for whatever creates and stores the passkey: your iPhone's built-in password manager, a YubiKey plugged into a laptop, Google Password Manager on Android, and so on. The AAGUID is a unique identifier for that authenticator's make and model: think of it as a product ID baked into every passkey the authenticator creates.",[13,505,506],{},"It is embedded in the attestation data that comes back from the browser's credentials API. But should you do anything with it? Yes, we think so.",[13,508,509],{},"A couple of things worth clarifying:",[13,511,512,515,516,138],{},[17,513,514],{},"Every passkey from the same authenticator type shares the same AAGUID."," Every credential created in Apple Passwords on any Apple device has the same AAGUID. It identifies the software or hardware model, not the individual device. The AAGUID for Apple Passwords is always ",[422,517,518],{},"fbfc3007-154e-4ecc-8c0b-6e020557d7bd",[13,520,521,58,524,527],{},[17,522,523],{},"Some authenticators send the zero AAGUID.",[422,525,526],{},"00000000-0000-0000-0000-000000000000"," is a valid AAGUID that means \"I am not telling you who I am.\" Some authenticators use this by choice. When you see it, there is nothing to look up and no way to determine the authenticator type.",[34,529],{},[37,531,533],{"id":532},"the-open-source-lookup-list","The open source lookup list",[13,535,536,537,539],{},"A raw UUID is not useful on its own. To go from ",[422,538,518],{}," to \"Apple Passwords\", you need a lookup table.",[13,541,542,543,549],{},"The community-maintained ",[60,544,548],{"href":545,"rel":546},"https:\u002F\u002Fgithub.com\u002Fpasskeydeveloper\u002Fpasskey-authenticator-aaguids",[547],"nofollow","passkey-authenticator-aaguids"," is a JSON file mapping AAGUIDs to human-readable names and optional icons. It is updated regularly as new authenticators come to market and covers over a thousand authenticators as of mid-2026.",[13,551,552],{},"The lookup list looks like this:",[481,554,558],{"className":555,"code":556,"language":557,"meta":354,"style":354},"language-json shiki shiki-themes github-light github-dark","{\n  \"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\": {\n    \"name\": \"Apple Passwords\",\n    \"icon_light\": \"...\",\n    \"icon_dark\": \"...\"\n  },\n  \"ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4\": {\n    \"name\": \"Google Password Manager\",\n    \"icon_light\": \"...\",\n    \"icon_dark\": \"...\"\n  }\n}\n","json",[422,559,560,568,577,592,605,616,622,630,642,653,662,668],{"__ignoreMap":354},[561,562,564],"span",{"class":563,"line":375},"line",[561,565,567],{"class":566},"sVt8B","{\n",[561,569,570,574],{"class":563,"line":355},[561,571,573],{"class":572},"sj4cs","  \"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\"",[561,575,576],{"class":566},": {\n",[561,578,579,582,585,589],{"class":563,"line":361},[561,580,581],{"class":572},"    \"name\"",[561,583,584],{"class":566},": ",[561,586,588],{"class":587},"sZZnC","\"Apple Passwords\"",[561,590,591],{"class":566},",\n",[561,593,595,598,600,603],{"class":563,"line":594},4,[561,596,597],{"class":572},"    \"icon_light\"",[561,599,584],{"class":566},[561,601,602],{"class":587},"\"...\"",[561,604,591],{"class":566},[561,606,608,611,613],{"class":563,"line":607},5,[561,609,610],{"class":572},"    \"icon_dark\"",[561,612,584],{"class":566},[561,614,615],{"class":587},"\"...\"\n",[561,617,619],{"class":563,"line":618},6,[561,620,621],{"class":566},"  },\n",[561,623,625,628],{"class":563,"line":624},7,[561,626,627],{"class":572},"  \"ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4\"",[561,629,576],{"class":566},[561,631,633,635,637,640],{"class":563,"line":632},8,[561,634,581],{"class":572},[561,636,584],{"class":566},[561,638,639],{"class":587},"\"Google Password Manager\"",[561,641,591],{"class":566},[561,643,645,647,649,651],{"class":563,"line":644},9,[561,646,597],{"class":572},[561,648,584],{"class":566},[561,650,602],{"class":587},[561,652,591],{"class":566},[561,654,656,658,660],{"class":563,"line":655},10,[561,657,610],{"class":572},[561,659,584],{"class":566},[561,661,615],{"class":587},[561,663,665],{"class":563,"line":664},11,[561,666,667],{"class":566},"  }\n",[561,669,671],{"class":563,"line":670},12,[561,672,673],{"class":566},"}\n",[13,675,676],{},"Using it in a backend is simple: at registration, extract the AAGUID from the response, look it up in the list, and store the resolved name alongside the credential. But remember, quite a few passkeys will have the zero AAGUID; in those cases you cannot identify the authenticator type.",[34,678],{},[37,680,682],{"id":681},"why-this-matters-for-your-users","Why this matters for your users",[13,684,685],{},"Consider a user who has registered three passkeys: one in Apple Passwords on their iPhone, one in LastPass on their laptop, and one on a YubiKey they carry as a backup. How you label these has a significant impact on whether the user can actually manage them. Note that a label is not an inherent part of passkeys, and not part of any spec. It is just a convenient way to identify the authenticator type for the user, typically in a user settings panel.",[13,687,688,691],{},[17,689,690],{},"No labels."," Many implementations show nothing useful: Imagine if you have registered three passkeys and the service only shows \"Passkey\" for all of them. You cannot tell which is which, and if you wanted to remove one of them - good luck guessing!",[13,693,694,697],{},[17,695,696],{},"OS and browser labels."," Some services record the browser and operating system at registration time, producing something like \"macOS Chrome\" as a label. However, this only tells the user when and where they happened to register, not what the passkey actually is. It could be that they actually stored their passkey in the 1Password password manager, and labeling the passkey \"macOS Chrome\" is then very misleading because they might as well be using that passkey on a Windows machine in Firefox the next day.",[13,699,700,703],{},[17,701,702],{},"AAGUID labels."," With a simple AAGUID lookup as your application registers a new passkey, the three anonymous passkeys could instead become \"Apple Passwords\", \"Proton Pass\", and \"YubiKey 5 NFC\". The user immediately knows what each one is. This is much more manageable and user friendly.",[34,705],{},[37,707,709],{"id":708},"plainkey-handles-labeling-passkeys-automatically-from-aaguids","PlainKey handles labeling passkeys automatically from AAGUID's",[13,711,712],{},"PlainKey does the AAGUID lookup at the point of registration. When a user registers a passkey on your site, PlainKey resolves the AAGUID against a local copy of the community list and stores both the raw AAGUID and the resolved name on the credential (we call it the authenticator type).",[13,714,715],{},"That authenticator type name also becomes the initial label. A passkey created in Apple Passwords shows up in your credential list as \"Apple Passwords\", with no code on your part.",[13,717,718],{},"Users can rename their labels at any time (if you let them that is, using our APIs and SDKs) to something personal like \"Work laptop\" or \"Spare key\". But they start from something recognisable rather than a blank field.",[13,720,721],{},"Every credential PlainKey returns includes both fields:",[481,723,727],{"className":724,"code":725,"language":726,"meta":354,"style":354},"language-ts shiki shiki-themes github-light github-dark","{\n  id: \"87e03816-41bc-4328-8b85-0f815d169fc2\",\n  aaguid: \"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\",\n  authenticatorType: \"Apple Passwords\", \u002F\u002F resolved at registration, static\n  label: \"Apple Passwords\", \u002F\u002F user-editable, you just use our API to let them update.\n  \u002F\u002F ...\n}\n","ts",[422,728,729,733,746,758,774,788,793],{"__ignoreMap":354},[561,730,731],{"class":563,"line":375},[561,732,567],{"class":566},[561,734,735,739,741,744],{"class":563,"line":355},[561,736,738],{"class":737},"sScJk","  id",[561,740,584],{"class":566},[561,742,743],{"class":587},"\"87e03816-41bc-4328-8b85-0f815d169fc2\"",[561,745,591],{"class":566},[561,747,748,751,753,756],{"class":563,"line":361},[561,749,750],{"class":737},"  aaguid",[561,752,584],{"class":566},[561,754,755],{"class":587},"\"fbfc3007-154e-4ecc-8c0b-6e020557d7bd\"",[561,757,591],{"class":566},[561,759,760,763,765,767,770],{"class":563,"line":594},[561,761,762],{"class":737},"  authenticatorType",[561,764,584],{"class":566},[561,766,588],{"class":587},[561,768,769],{"class":566},", ",[561,771,773],{"class":772},"sJ8bj","\u002F\u002F resolved at registration, static\n",[561,775,776,779,781,783,785],{"class":563,"line":607},[561,777,778],{"class":737},"  label",[561,780,584],{"class":566},[561,782,588],{"class":587},[561,784,769],{"class":566},[561,786,787],{"class":772},"\u002F\u002F user-editable, you just use our API to let them update.\n",[561,789,790],{"class":563,"line":618},[561,791,792],{"class":772},"  \u002F\u002F ...\n",[561,794,795],{"class":563,"line":624},[561,796,673],{"class":566},[13,798,799,802,803,806],{},[422,800,801],{},"authenticatorType"," reflects what was resolved at registration and never changes. ",[422,804,805],{},"label"," is user-editable.",[34,808],{},[37,810,812],{"id":811},"getting-started","Getting started",[13,814,815,816,820],{},"If you are looking to add passkeys to your web app with automatic AAGUID lookup, ",[60,817,7],{"href":818,"rel":819},"https:\u002F\u002Fplainkey.io",[547]," handles all the time-consuming stuff around passkeys for you. That includes credential storage, challenge generation, signature verification, and AAGUID lookup out of the box. You can start out for free for a small amount of passkey registrations, so it's easy to get started.",[822,823,824],"style",{},"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}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 .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":354,"searchDepth":355,"depth":355,"links":826},[827,828,829,830,831],{"id":499,"depth":355,"text":500},{"id":532,"depth":355,"text":533},{"id":681,"depth":355,"text":682},{"id":708,"depth":355,"text":709},{"id":811,"depth":355,"text":812},"Every passkey registration includes an AAGUID that identifies which password manager or hardware device created it. Here is what that means and how to use it.",{},"\u002Farticles\u002Faaguids-and-passkey-authenticator-types",{"title":470,"description":832},"articles\u002Faaguids-and-passkey-authenticator-types","zju97VK_B4gndZtDu1l12Lbm5K8z67CYeUznha9dOuU",{"id":839,"title":840,"author":841,"body":842,"date":371,"description":893,"extension":373,"image":8,"meta":894,"navigation":376,"path":895,"seo":896,"stem":897,"tags":8,"__hash__":898},"articles\u002Farticles\u002Fabout.md","About PlainKey",{"name":7,"avatar":8},{"type":10,"value":843,"toc":890},[844,847,850,853,856,858,862,870,873,876,878],[13,845,846],{},"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,848,849],{},"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,851,852],{},"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,854,855],{},"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.",[34,857],{},[37,859,861],{"id":860},"who-is-behind-plainkey","Who is behind PlainKey?",[13,863,864,865,869],{},"PlainKey is built by ",[60,866,386],{"href":867,"rel":868},"https:\u002F\u002Fsteen.cc",[547],", a software developer based in Oslo, Norway.",[13,871,872],{},"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,874,875],{},"PlainKey AS is a publicly registered Norwegian limited company.",[34,877],{},[13,879,880,881,885,886,138],{},"Read the ",[60,882,884],{"href":883},"\u002Fdocs\u002Fgetting-started","getting started guide"," or ",[60,887,889],{"href":888},"\u002Farticles\u002Flearn-more","learn more about how PlainKey works",{"title":354,"searchDepth":355,"depth":355,"links":891},[892],{"id":860,"depth":355,"text":861},"The story behind PlainKey and who built it.",{},"\u002Farticles\u002Fabout",{"title":840,"description":893},"articles\u002Fabout","OcJSaDqBjwa4a89fWFPCiGh6L6yMzIvg4S-lBe0einE",{"id":900,"title":901,"author":902,"body":903,"date":1188,"description":1189,"extension":373,"image":8,"meta":1190,"navigation":376,"path":1191,"seo":1192,"stem":1193,"tags":8,"__hash__":1194},"articles\u002Farticles\u002Fhow-to-add-passkeys-to-your-website.md","How to add passkeys to your website",{"name":7,"avatar":8},{"type":10,"value":904,"toc":1177},[905,908,911,913,917,920,923,926,937,940,942,946,949,952,955,958,960,964,970,973,991,995,1083,1086,1090,1121,1128,1132,1135,1143,1145,1149,1152,1155,1158,1160,1162,1174],[13,906,907],{},"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,909,910],{},"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.",[34,912],{},[37,914,916],{"id":915},"what-passkeys-are","What passkeys are",[13,918,919],{},"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,921,922],{},"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,924,925],{},"A few things that make passkeys genuinely better than passwords:",[99,927,928,931,934],{},[102,929,930],{},"They are phishing-resistant. Passkeys are bound to a specific domain and will not work on fake login pages.",[102,932,933],{},"Even if your server is breached, there are no passwords to steal. The private key never left the user's device.",[102,935,936],{},"They are an industry standard, supported across all modern browsers and platforms - Chrome, Safari, Firefox, iOS, Android, Windows.",[13,938,939],{},"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.",[34,941],{},[37,943,945],{"id":944},"what-raw-webauthn-implementation-involves","What raw WebAuthn implementation involves",[13,947,948],{},"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,950,951],{},"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,953,954],{},"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,956,957],{},"It is doable. It is also a meaningful project before you have written a single line of your actual application.",[34,959],{},[37,961,963],{"id":962},"adding-passkeys-with-plainkey","Adding passkeys with PlainKey",[13,965,966,969],{},[60,967,7],{"href":818,"rel":968},[547]," 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,971,972],{},"To install the PlainKey browser library, run the following in your project terminal:",[481,974,978],{"className":975,"code":976,"language":977,"meta":354,"style":354},"language-bash shiki shiki-themes github-light github-dark","npm install @plainkey\u002Fbrowser\n","bash",[422,979,980],{"__ignoreMap":354},[561,981,982,985,988],{"class":563,"line":375},[561,983,984],{"class":737},"npm",[561,986,987],{"class":587}," install",[561,989,990],{"class":587}," @plainkey\u002Fbrowser\n",[84,992,994],{"id":993},"sign-up-registering-a-new-user-with-a-passkey","Sign up - registering a new user with a passkey",[481,996,998],{"className":724,"code":997,"language":726,"meta":354,"style":354},"import { PlainKey } from \"@plainkey\u002Fbrowser\"\nconst plainKey = new PlainKey(\"YOUR_PROJECT_ID\")\n\nconst { data, error } = await plainKey.createUserWithPasskey(\"user@example.com\")\n",[422,999,1000,1015,1041,1046],{"__ignoreMap":354},[561,1001,1002,1006,1009,1012],{"class":563,"line":375},[561,1003,1005],{"class":1004},"szBVR","import",[561,1007,1008],{"class":566}," { PlainKey } ",[561,1010,1011],{"class":1004},"from",[561,1013,1014],{"class":587}," \"@plainkey\u002Fbrowser\"\n",[561,1016,1017,1020,1023,1026,1029,1032,1035,1038],{"class":563,"line":355},[561,1018,1019],{"class":1004},"const",[561,1021,1022],{"class":572}," plainKey",[561,1024,1025],{"class":1004}," =",[561,1027,1028],{"class":1004}," new",[561,1030,1031],{"class":737}," PlainKey",[561,1033,1034],{"class":566},"(",[561,1036,1037],{"class":587},"\"YOUR_PROJECT_ID\"",[561,1039,1040],{"class":566},")\n",[561,1042,1043],{"class":563,"line":361},[561,1044,1045],{"emptyLinePlaceholder":376},"\n",[561,1047,1048,1050,1053,1056,1058,1061,1064,1067,1070,1073,1076,1078,1081],{"class":563,"line":594},[561,1049,1019],{"class":1004},[561,1051,1052],{"class":566}," { ",[561,1054,1055],{"class":572},"data",[561,1057,769],{"class":566},[561,1059,1060],{"class":572},"error",[561,1062,1063],{"class":566}," } ",[561,1065,1066],{"class":1004},"=",[561,1068,1069],{"class":1004}," await",[561,1071,1072],{"class":566}," plainKey.",[561,1074,1075],{"class":737},"createUserWithPasskey",[561,1077,1034],{"class":566},[561,1079,1080],{"class":587},"\"user@example.com\"",[561,1082,1040],{"class":566},[13,1084,1085],{},"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.",[84,1087,1089],{"id":1088},"sign-in-authenticating-an-existing-user","Sign in - authenticating an existing user",[481,1091,1093],{"className":724,"code":1092,"language":726,"meta":354,"style":354},"const { data, error } = await plainKey.authenticate()\n",[422,1094,1095],{"__ignoreMap":354},[561,1096,1097,1099,1101,1103,1105,1107,1109,1111,1113,1115,1118],{"class":563,"line":375},[561,1098,1019],{"class":1004},[561,1100,1052],{"class":566},[561,1102,1055],{"class":572},[561,1104,769],{"class":566},[561,1106,1060],{"class":572},[561,1108,1063],{"class":566},[561,1110,1066],{"class":1004},[561,1112,1069],{"class":1004},[561,1114,1072],{"class":566},[561,1116,1117],{"class":737},"authenticate",[561,1119,1120],{"class":566},"()\n",[13,1122,1123,1124,1127],{},"Calling ",[422,1125,1126],{},".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.",[84,1129,1131],{"id":1130},"the-backend-step","The backend step",[13,1133,1134],{},"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,1136,1137,1138,138],{},"The full backend walkthrough is in the ",[60,1139,1142],{"href":1140,"rel":1141},"https:\u002F\u002Fplainkey.io\u002Fdocs",[547],"PlainKey docs",[34,1144],{},[37,1146,1148],{"id":1147},"what-plainkey-provides","What PlainKey provides",[13,1150,1151],{},"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,1153,1154],{},"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,1156,1157],{},"What you handle: your app's UI, a few SDK calls, and your own user database and backend.",[34,1159],{},[37,1161,812],{"id":811},[13,1163,1164,1165,1169,1170,1173],{},"Sign up at ",[60,1166,1168],{"href":818,"rel":1167},[547],"plainkey.io",", create a project, and you will have a project ID within a minute. For local development, use ",[422,1171,1172],{},"localhost"," as your domain when creating the project.",[822,1175,1176],{},"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":354,"searchDepth":355,"depth":355,"links":1178},[1179,1180,1181,1186,1187],{"id":915,"depth":355,"text":916},{"id":944,"depth":355,"text":945},{"id":962,"depth":355,"text":963,"children":1182},[1183,1184,1185],{"id":993,"depth":361,"text":994},{"id":1088,"depth":361,"text":1089},{"id":1130,"depth":361,"text":1131},{"id":1147,"depth":355,"text":1148},{"id":811,"depth":355,"text":812},"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":901,"description":1189},"articles\u002Fhow-to-add-passkeys-to-your-website","kZHuvHWCBNY_5yJmnhrZJ7Zkku-xvsyV4BGxKN2fnkc",{"id":1196,"title":1197,"author":1198,"body":1199,"date":371,"description":1372,"extension":373,"image":8,"meta":1373,"navigation":376,"path":888,"seo":1374,"stem":1375,"tags":8,"__hash__":1376},"articles\u002Farticles\u002Flearn-more.md","Passkeys and PlainKey",{"name":7,"avatar":8},{"type":10,"value":1200,"toc":1366},[1201,1207,1209,1213,1216,1219,1222,1228,1230,1234,1237,1240,1242,1246,1257,1260,1263,1332,1335,1338,1343,1345,1349,1352,1354,1364],[13,1202,1203,1204,138],{},"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 ",[60,1205,1206],{"href":895},"about page",[34,1208],{},[37,1210,1212],{"id":1211},"what-is-a-passkey","What is a passkey?",[13,1214,1215],{},"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,1217,1218],{},"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,1220,1221],{},"Passkeys are built on WebAuthn, which all modern browsers and platforms support.",[1223,1224,1225],"info",{},[13,1226,1227],{},"Passkeys work for sign-in, as a second factor (2FA\u002FMFA), or to verify a user before a sensitive action.",[34,1229],{},[37,1231,1233],{"id":1232},"implementing-webauthn-yourself","Implementing WebAuthn yourself",[13,1235,1236],{},"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,1238,1239],{},"All this takes time you might want to spend on building your product instead. And getting any of this wrong can introduce security vulnerabilities.",[34,1241],{},[37,1243,1245],{"id":1244},"using-plainkey","Using PlainKey",[13,1247,1248,1249,1252,1253,1256],{},"You integrate with PlainKey via the npm package ",[422,1250,1251],{},"@plainkey\u002Fbrowser"," in the frontend, and the npm package ",[422,1254,1255],{},"@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,1258,1259],{},"The APIs and SDKs are designed with two main goals in mind: simplicity and security.",[13,1261,1262],{},"The docs cover the full integration in more detail. Browser-side, authenticating a user essentially looks like this:",[481,1264,1268],{"className":1265,"code":1266,"language":1267,"meta":354,"style":354},"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",[422,1269,1270,1284,1288,1307],{"__ignoreMap":354},[561,1271,1272,1274,1276,1278,1281],{"class":563,"line":375},[561,1273,1005],{"class":1004},[561,1275,1008],{"class":566},[561,1277,1011],{"class":1004},[561,1279,1280],{"class":587}," \"@plainkey\u002Fbrowser\"",[561,1282,1283],{"class":566},";\n",[561,1285,1286],{"class":563,"line":355},[561,1287,1045],{"emptyLinePlaceholder":376},[561,1289,1290,1292,1294,1296,1298,1300,1302,1304],{"class":563,"line":361},[561,1291,1019],{"class":1004},[561,1293,1022],{"class":572},[561,1295,1025],{"class":1004},[561,1297,1028],{"class":1004},[561,1299,1031],{"class":737},[561,1301,1034],{"class":566},[561,1303,1037],{"class":587},[561,1305,1306],{"class":566},");\n",[561,1308,1309,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329],{"class":563,"line":594},[561,1310,1019],{"class":1004},[561,1312,1052],{"class":566},[561,1314,1055],{"class":572},[561,1316,769],{"class":566},[561,1318,1060],{"class":572},[561,1320,1063],{"class":566},[561,1322,1066],{"class":1004},[561,1324,1069],{"class":1004},[561,1326,1072],{"class":566},[561,1328,1117],{"class":737},[561,1330,1331],{"class":566},"();\n",[13,1333,1334],{},"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,1336,1337],{},"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.",[1223,1339,1340],{},[13,1341,1342],{},"PlainKey stores only the data required for passkey management. You can even opt not to send usernames or email addresses to PlainKey at all.",[34,1344],{},[37,1346,1348],{"id":1347},"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,1350,1351],{},"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.",[34,1353],{},[13,1355,880,1356,1358,1359,138],{},[60,1357,884],{"href":883}," or try the ",[60,1360,1363],{"href":1361,"rel":1362},"https:\u002F\u002Fdemo.plainkey.io",[547],"demo",[822,1365,1176],{},{"title":354,"searchDepth":355,"depth":355,"links":1367},[1368,1369,1370,1371],{"id":1211,"depth":355,"text":1212},{"id":1232,"depth":355,"text":1233},{"id":1244,"depth":355,"text":1245},{"id":1347,"depth":355,"text":1348},"What passkeys are and how PlainKey handles them for you.",{},{"title":1197,"description":1372},"articles\u002Flearn-more","Qhy8E5fpSe6QzkLp9hw_VjIJlOgxdbkB6XXQOgfrpuA",{"id":4,"title":5,"author":1378,"body":1379,"date":371,"description":372,"extension":373,"image":8,"meta":1622,"navigation":376,"path":377,"seo":1623,"stem":379,"tags":8,"__hash__":380},{"name":7,"avatar":8},{"type":10,"value":1380,"toc":1607},[1381,1389,1391,1393,1395,1397,1409,1411,1415,1417,1419,1421,1423,1427,1429,1445,1447,1449,1451,1455,1457,1467,1469,1479,1481,1485,1487,1489,1491,1503,1505,1507,1509,1511,1525,1527,1529,1531,1533,1535,1537,1539,1547,1549,1551,1553,1563,1565,1567,1569,1573,1575,1577,1579,1593,1599,1601,1603,1605],[13,1382,15,1383,19,1385,19,1387,26],{},[17,1384,7],{},[17,1386,22],{},[17,1388,25],{},[13,1390,29],{},[13,1392,32],{},[34,1394],{},[37,1396,40],{"id":39},[13,1398,1399,46,1401,50,1403,54,1405,58,1407],{},[17,1400,45],{},[17,1402,49],{},[17,1404,53],{},[17,1406,57],{},[60,1408,63],{"href":62},[13,1410,66],{},[13,1412,69,1413,73],{},[17,1414,72],{},[34,1416],{},[37,1418,79],{"id":78},[13,1420,82],{},[84,1422,87],{"id":86},[13,1424,90,1425,94],{},[17,1426,93],{},[13,1428,97],{},[99,1430,1431,1433,1435,1437,1439,1441,1443],{},[102,1432,104],{},[102,1434,107],{},[102,1436,110],{},[102,1438,113],{},[102,1440,116],{},[102,1442,119],{},[102,1444,122],{},[13,1446,125],{},[34,1448],{},[84,1450,131],{"id":130},[13,1452,134,1453,138],{},[17,1454,137],{},[13,1456,141],{},[99,1458,1459,1463],{},[102,1460,146,1461],{},[17,1462,149],{},[102,1464,1465],{},[17,1466,154],{},[13,1468,157],{},[99,1470,1471,1473,1475,1477],{},[102,1472,162],{},[102,1474,116],{},[102,1476,113],{},[102,1478,119],{},[13,1480,125],{},[13,1482,173,1483,177],{},[17,1484,176],{},[34,1486],{},[37,1488,183],{"id":182},[13,1490,186],{},[99,1492,1493,1495,1497,1499,1501],{},[102,1494,191],{},[102,1496,194],{},[102,1498,197],{},[102,1500,200],{},[102,1502,203],{},[13,1504,206],{},[34,1506],{},[37,1508,212],{"id":211},[13,1510,215],{},[99,1512,1513,1517,1521],{},[102,1514,1515,223],{},[17,1516,222],{},[102,1518,1519,229],{},[17,1520,228],{},[102,1522,1523,235],{},[17,1524,234],{},[34,1526],{},[37,1528,241],{"id":240},[13,1530,244],{},[13,1532,247],{},[34,1534],{},[37,1536,253],{"id":252},[13,1538,256],{},[99,1540,1541,1543,1545],{},[102,1542,261],{},[102,1544,264],{},[102,1546,267],{},[34,1548],{},[37,1550,273],{"id":272},[13,1552,276],{},[99,1554,1555,1557,1559,1561],{},[102,1556,281],{},[102,1558,284],{},[102,1560,287],{},[102,1562,290],{},[13,1564,293],{},[34,1566],{},[37,1568,299],{"id":298},[13,1570,302,1571,138],{},[60,1572,63],{"href":62},[34,1574],{},[37,1576,310],{"id":309},[13,1578,313],{},[99,1580,1581,1583,1585,1587,1589,1591],{},[102,1582,318],{},[102,1584,321],{},[102,1586,324],{},[102,1588,327],{},[102,1590,330],{},[102,1592,333],{},[13,1594,336,1595,138],{},[17,1596,1597],{},[60,1598,63],{"href":62},[13,1600,343],{},[34,1602],{},[37,1604,349],{"id":348},[13,1606,352],{},{"title":354,"searchDepth":355,"depth":355,"links":1608},[1609,1610,1614,1615,1616,1617,1618,1619,1620,1621],{"id":39,"depth":355,"text":40},{"id":78,"depth":355,"text":79,"children":1611},[1612,1613],{"id":86,"depth":361,"text":87},{"id":130,"depth":361,"text":131},{"id":182,"depth":355,"text":183},{"id":211,"depth":355,"text":212},{"id":240,"depth":355,"text":241},{"id":252,"depth":355,"text":253},{"id":272,"depth":355,"text":273},{"id":298,"depth":355,"text":299},{"id":309,"depth":355,"text":310},{"id":348,"depth":355,"text":349},{"version":375},{"title":5,"description":372},{"id":1625,"title":1626,"author":1627,"body":1628,"date":371,"description":1795,"extension":373,"image":8,"meta":1796,"navigation":376,"path":1797,"seo":1798,"stem":1799,"tags":8,"__hash__":1800},"articles\u002Farticles\u002Fterms.md","Terms of Use",{"name":7,"avatar":8},{"type":10,"value":1629,"toc":1782},[1630,1633,1636,1638,1642,1645,1648,1659,1661,1665,1668,1676,1678,1682,1685,1688,1691,1693,1697,1700,1703,1705,1709,1712,1717,1719,1723,1728,1730,1734,1739,1742,1744,1748,1751,1753,1757,1760,1762,1766,1769,1771,1775,1778],[13,1631,1632],{},"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,1634,1635],{},"By creating an account or using the service, you agree to these Terms.",[34,1637],{},[37,1639,1641],{"id":1640},"_1-use-of-the-service","1. Use of the service",[13,1643,1644],{},"You agree to use PlainKey only for lawful purposes and in accordance with these Terms.",[13,1646,1647],{},"You must not:",[99,1649,1650,1653,1656],{},[102,1651,1652],{},"attempt to gain unauthorised access to the service or its systems",[102,1654,1655],{},"interfere with or disrupt the service",[102,1657,1658],{},"use the service in a way that violates applicable laws or regulations",[34,1660],{},[37,1662,1664],{"id":1663},"_2-accounts-and-security","2. Accounts and security",[13,1666,1667],{},"You are responsible for maintaining the security of your account and for all activity carried out under it.",[13,1669,1670,1671,1675],{},"If you believe your account has been compromised, notify us at ",[60,1672,1674],{"href":1673},"mailto:hello@plainkey.io","hello@plainkey.io"," as soon as possible.",[34,1677],{},[37,1679,1681],{"id":1680},"_3-availability","3. Availability",[13,1683,1684],{},"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,1686,1687],{},"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,1689,1690],{},"Customers remain responsible for the security of their applications, and for ensuring that their use of PlainKey meets their own security and compliance requirements.",[34,1692],{},[37,1694,1696],{"id":1695},"_4-limitation-of-liability","4. Limitation of liability",[13,1698,1699],{},"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,1701,1702],{},"PlainKey is not liable for indirect or consequential damages, including loss of profit, loss of data, or loss of goodwill.",[34,1704],{},[37,1706,1708],{"id":1707},"_5-suspension-and-termination","5. Suspension and termination",[13,1710,1711],{},"We may suspend or terminate access to the service in cases of misuse, security concerns, or violations of these Terms.",[13,1713,1714,1715,138],{},"You may stop using the service at any time. To delete your account and associated data, contact us at ",[60,1716,1674],{"href":1673},[34,1718],{},[37,1720,1722],{"id":1721},"_6-data-portability","6. Data portability",[13,1724,1725,1726,138],{},"You may request an export of your data at any time by contacting ",[60,1727,1674],{"href":1673},[34,1729],{},[37,1731,1733],{"id":1732},"_7-privacy-and-data-protection","7. Privacy and data protection",[13,1735,1736,1737,138],{},"Our processing of personal data is described in our ",[17,1738,5],{},[13,1740,1741],{},"Where PlainKey processes personal data on behalf of customers, customers remain responsible for ensuring appropriate notices and legal bases for their end users.",[34,1743],{},[37,1745,1747],{"id":1746},"_8-pricing","8. Pricing",[13,1749,1750],{},"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.",[34,1752],{},[37,1754,1756],{"id":1755},"_9-changes-to-these-terms","9. Changes to these Terms",[13,1758,1759],{},"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.",[34,1761],{},[37,1763,1765],{"id":1764},"_10-governing-law-and-disputes","10. Governing law and disputes",[13,1767,1768],{},"These Terms are governed by Norwegian law.",[34,1770],{},[37,1772,1774],{"id":1773},"_11-contact","11. Contact",[13,1776,1777],{},"If you have questions about these Terms, contact us at:",[13,1779,1780],{},[60,1781,1674],{"href":1673},{"title":354,"searchDepth":355,"depth":355,"links":1783},[1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794],{"id":1640,"depth":355,"text":1641},{"id":1663,"depth":355,"text":1664},{"id":1680,"depth":355,"text":1681},{"id":1695,"depth":355,"text":1696},{"id":1707,"depth":355,"text":1708},{"id":1721,"depth":355,"text":1722},{"id":1732,"depth":355,"text":1733},{"id":1746,"depth":355,"text":1747},{"id":1755,"depth":355,"text":1756},{"id":1764,"depth":355,"text":1765},{"id":1773,"depth":355,"text":1774},"This document explains the terms and conditions for using PlainKey.",{"version":375},"\u002Farticles\u002Fterms",{"title":1626,"description":1795},"articles\u002Fterms","MXAj7uFp_RiDAEbSujvDRiPds9EKuJs9ukceFtn3MOo",1781381597695]