Apereo CAS - QR Code Authentication

Posted by Misagh Moayyed on August 19, 2022 · 6 mins read ·

Apereo CAS can allow mobile applications and devices to let the user to scan a CAS-generaterd QR code and subsequently login after having successfully validated it. This post looks at a brief implementation of QR Code Authentication in Apereo CAS.

This post specifically requires and focuses on:


The QR code generated by CAS contains a special identifier embedded within that allows the mobile device to establish a communication channel using web sockets to the CAS server. Once the connection is established, the mobile device may collect credentials from the user and submit those to CAS for verification. The returned result, expected as a JWT that is generated by CAS, is then passed along to the web socket channel for verification and successful login.

Subsequent login attempts can allow for a completely passwordless scenario such that the mobile device can continue to re-use the JWT for authentication attempts, allowing the end user to scan and proceed. Once presented to the user, the initial QR code and login screen would be similar to the following image:

Communication Channel

Once the channel id is retrieved after the QR code scan, the client application would need to establish a web socket communication channel with CAS. For example, a Node.js client application might want to do the following:

const client = new StompJS.Client({
    brokerURL: 'ws://sso.example.org/cas/qr-websocket',
    debug: str => {

if (typeof WebSocket !== 'function') {
    client.webSocketFactory = () => new SockJS('https://sso.example.org/cas/qr-websocket');

client.onConnect = frame => {
    // we have a connection available


At this point, the mobile application would ask the user to provide a username/password to establish an initial identity. The credentials are then passed to CAS to get back the appropriate authentication token as a JWT. Once the JWT is passed back by CAS to the application, it is then passed to the web socket channel to allow CAS to proceed and login.

const deviceId = `...`;
const parameters = `username=casuser&password=Mellon&token=true&QR_AUTHENTICATION_DEVICE_ID=${deviceId}`;
executeRequest(`https://sso.example.org/cas/v1/tickets?${parameters}`, 201)
  .then(token => {
      let payload = JSON.stringify({'token': token});
          destination: "/qr/accept",
          headers: {
              'QR_AUTHENTICATION_CHANNEL_ID': channelIdFromTheQRCode,
              'QR_AUTHENTICATION_DEVICE_ID': deviceId
          body: payload

There are two special headers that are passed back to CAS:

  • QR_AUTHENTICATION_CHANNEL_ID: this is the same channel id that was once obtained via a QR code scan.
  • QR_AUTHENTICATION_DEVICE_ID: This is the device identifier. Registered devices are authorized and accepted by CAS using a dedicated QR device repository, that is able to track and link device identifiers to user ids. Such devices must be registered with CAS using an external registration mechanism or via available CAS-provided APIs. By default, all devices can authenticate using the QR code.

Need Help?

If you have questions about the contents and the topic of this blog post, or if you need additional guidance and support, feel free to send us a note and ask about consulting and support services.


I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.

Misagh Moayyed