Post

Use Captcha With Nuxt And Ssr

This is a follow-up to New Form Captcha Features, to integrate the Altcha captcha on Nuxt.js with SSR (server side rendering) enabled. If you are looking to integrate a captcha with React, Vue or others, please refer to this previous post.

Implementation

To use the capcha with Nuxt.js (v2) and SSR (server side rendering), some additional work is needed because Altcha is designed to work in the browser.

1. Load the Altcha Library

Create a new plugin file plugins/altcha.client.ts:

1
import 'altcha'
2. Configure Nuxt.js

Extend your nuxt.config.ts:

1
2
3
4
5
6
7
8
9
10
11
[
  // other settings
  plugins: [
    { src: '~/plugins/altcha.client', mode: 'client' },
  ],
  build: {
    transpile: [
      'altcha',
    ],
  },
]
3. Embed the Captcha

Add the Captcha to your component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<template>
  <ValidationObserver ref="observer" v-slot="{ handleSubmit }">
    <ValidationProvider v-slot="{ errors, valid }" rules="required" name="firstName">
      <b-field
        label="First Name*"
        :type="{
          'is-danger': errors[0],
          'is-success': valid,
        }"
        :message="errors"
      >
        <b-input v-model="form.firstName" placeholder="Mike" />
      </b-field>
    </ValidationProvider>

    <ClientOnly>
      <altcha-widget
        ref="altchaWidget"
        :challengeurl="challengeUrl"
        hidefooter
        hidelogo
        @statechange="handleAltchaStateChange"
      ></altcha-widget>
    </ClientOnly>

    <b-button type="is-primary" style="margin-top: 1rem" @click="handleSubmit(submit)"> Submit </b-button>
  </ValidationObserver>
</template>

<script lang="ts">
import { ref } from 'vue'
import { Vue, Component } from 'nuxt-property-decorator'
import { ValidationProvider, ValidationObserver } from 'vee-validate'

@Component({
  components: {
    ValidationObserver,
    ValidationProvider,
  },
})
export default class ContactForm extends Vue {
  submissionSuccess: boolean = false

  // Replace these URLs with your own
  formUrl = 'https://api.rusty-forms.com/v1/digest/75abad84-7a8d-4075-b18f-cd35954b9df6'
  challengeUrl = 'https://api.rusty-forms.com/v1/forms/75abad84-7a8d-4075-b18f-cd35954b9df6/challenge/altcha'

  // Reference to the altcha widget
  altchaWidget = ref<HTMLElement | null>(null);

  public form = {
    firstName: '',
    // other form fields
    altcha: ''
  }

  // Handle the captcha state change
  handleAltchaStateChange(event: CustomEvent<AltchaState>) {
    if (event.detail.state === 'verified') {
      this.form.altcha = event.detail.payload || '';
    } else {
      this.form.altcha = '';
    }
  }
  
  async mounted() {
    // Add the event listener to the altcha widget
    if (this.altchaWidget && this.altchaWidget.value) {
      (this.altchaWidget.value as any).addEventListener('statechange', this.handleAltchaStateChange);
    }
  }

  beforeDestroy() {
    // Remove the event listener from the altcha widget
    if (this.altchaWidget && this.altchaWidget.value) {
      (this.altchaWidget.value as any).removeEventListener('statechange', this.handleAltchaStateChange);
    }
  }

  async submit() {
    // Check if the captcha is completed
    if (this.form.altcha === '') {
      alert('Please complete the CAPTCHA.')
    }
    await this.$axios.$post(this.formUrl, this.form)
  }
}
</script>

This example includes some rudimentary form validation with VeeValidate. You can replace this with your own validation library or custom validation logic.

Steps to be aware of:

  • ClientOnly tag, to make sure the widget is only rendered on the client side
  • @statechange event listener, to handle the captcha state change
  • handleAltchaStateChange method, to update the form field with the captcha token
4. Add Typings

Create a typings.d.ts file in the root of your project:

1
2
3
4
5
6
interface AltchaState {
	state: 'unverified' | 'verifying' | 'verified' | 'error'
	payload?: string
}

type AltchaStateChangeEvent = CustomEvent<AltchaState>

That’s it. The Altcha captcha should now work with your Nuxt.js application and SSR enabled.

This post is licensed under CC BY 4.0 by the author.