:rfc_link: link:https://datatracker.ietf.org/doc/html/rfc7636[RFC 7636]
:toc: macro
:toclevels: 5
:figure-caption!:
= Proof Key for Code Exchange (PKCE)
Proof Key for Code Exchange (PKCE) is an authorization code flow extension to link:https://oauth.net[OAuth] which is necessary for mobile authentication but works well for web flows because the added security is transparent to the user. Specifically, PKCE prevents the following types of attacks:
- Authorization code interception
- Authorization code injection
This gem is an implementation of the {rfc_link} specification so you can leverage PKCE in your own code.
toc::[]
== Features
- Implements the {rfc_link} specification.
- Provides a simple object API for obtaining a challenge and verify code.
- Provides max length security by default.
- Answers a monad result.
== Requirements
. link:https://www.ruby-lang.org[Ruby].
. link:https://www.oauth.com[OAuth].
== Setup
To install with security, run:
[source,bash]
💡 Skip this line if you already have the public certificate installed.
gem cert --add <(curl --compressed --location https://alchemists.io/gems.pem)
gem install pkce --trust-policy HighSecurity
To install without security, run:
[source,bash]
gem install pkce
You can also add the gem directly to your project:
[source,bash]
bundle add pkce
Once the gem is installed, you only need to require it:
[source,ruby]
require "pkce"
== Usage
The object API is simple to work with as you only need to interact with the PKCE
constant. Example:
[source,ruby]
code = PKCE.call.success
code.challenge # e2tGChTfGON-C55i0yu13-urIgDFuMCmo73F7TZmoiw
code.verify # hYnx2WTJo7Bgu1-GqPUIYtRkb2W7pRBawkmdDi3omPdramb27Fp4rps_w6ozns-gbVCKFC2-Kno4P_b1H3FuxnlYIOd9Bo5yoTXq_xEHDJaB_fOfn2NaiCtcWQ8Bs91I
You can also pass in a custom length (default is maximum):
[source,ruby]
code = PKCE.call(length: 35).success
code.challenge # R1b1Ka3jmrLKvQ7xW5QmP5MsCSEWtdoA2lo3r-SZDfg
code.verify # ucKkqwoMzc9cyPcSGMbuVf3ivr4sep2mq15hGN9sVzl4X7g
In case of a failure, you'll get a proper error message:
[source,ruby]
PKCE.call(length: 100).failure # Invalid PKCE verifier length: 100. Must be between 32..96.
Due to the fact that PKCE answers back a link:https://dry-rb.org/gems/dry-monads[monad], you have all of the power of link:https://alchemists.io/talks/ruby_pattern_matching[pattern matching] at your fingertips as well:
[source,ruby]
include Dry::Monads[:result]
case PKCE.call
in Success(code) then puts code.inspect
in Failure(message) then puts message
end
Finally, since the code answered back is a link:https://alchemists.io/articles/ruby_data[Data] object that you can easily test and interact with:
[source,ruby]
PKCE.call.success
#<data PKCE::Code challenge="ROMnfvHt04xhM80WB2PyPK67GGrG35UdFEf0DEBkes0", verify="cUq917cDIROAUkew-OjIdfIz1OYyv-ERt9NnSdzlxz4XSYzdbRycVuRDD2SBIDBiKnXUamxvpxNRsUMBQ1PvBdtziGs_oYe98MDWmM8J2_NJQBVg2kP-B2OqBdMp00qh">
== Development
To contribute, run:
[source,bash]
You can also use the IRB console for direct access to all objects:
[source,bash]
bin/console
=== Architecture
The following documents the workflow used to process and build authorization codes.
image::https://alchemists.io/images/projects/pkce/doc/sequence_diagram.svg[Sequence Diagram]
== Tests
To test, run:
[source,bash]
bin/rake
== link:https://alchemists.io/policies/license[License]
== link:https://alchemists.io/policies/security[Security]
== link:https://alchemists.io/policies/code_of_conduct[Code of Conduct]
== link:https://alchemists.io/policies/contributions[Contributions]
== link:https://alchemists.io/policies/developer_certificate_of_origin[Developer Certificate of Origin]
== link:https://alchemists.io/projects/pkce/versions[Versions]
== link:https://alchemists.io/community[Community]
== Credits