Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Rails GraphQL Auth - JWT, Email & Security
Sulman Baig
Sulman Baig

Posted on • Originally published atsulmanweb.com

Rails GraphQL Auth - JWT, Email & Security

Building a secure and scalable authentication system is crucial for modern web applications. Today, I'll share insights from implementing a robust GraphQL authentication system in Rails, with detailed explanations of each component.

🏗️ Architecture Overview

The authentication system consists of three main components:

  1. JWT-based token authentication
  2. Email verification workflow
  3. Secure password management

Let's examine each component in detail.

🔑 JWT Authentication Implementation

Token Generation and Management

The core of our authentication relies on JWT tokens. Let's break down the key components:

classUser<ApplicationRecord# Token generation for different purposes with specific lifetimesgenerates_token_for:auth_token,expires_in:1.weekgenerates_token_for:email_confirmation,expires_in:8.hoursgenerates_token_for:password_reset,expires_in:1.hourend
Enter fullscreen modeExit fullscreen mode

This code uses a custom token generation system where:

  • generates_token_for is a macro that sets up token generation for specific purposes
  • Each token type has its own expiration time
  • Tokens are bound to specific user data for verification

For example, when we calluser.generate_token_for(:auth_token), it:

  1. Creates a JWT token with user-specific claims
  2. Sets an expiration time (1 week for auth tokens)
  3. Signs the token with the application's secret key
  4. Returns the encoded token for client use

Authentication Service

moduleUsersclassSignInService<ApplicationServicedefcallreturnfailure([USER_NOT_FOUND_MESSAGE])unlessuser# Generate authentication tokentoken=user.generate_token_for(:auth_token)# Log the authentication eventlog_event(user:,data:{username:user.username})# Return success response with token and user datasuccess({token:,user:})endprivatedefuser# Authenticate user using credentials@user||=User.authenticate_by(permitted_params)endendend
Enter fullscreen modeExit fullscreen mode

Key aspects of the service:

  1. Validates user credentials
  2. Generates an authentication token
  3. Logs the authentication event
  4. Returns a structured response

GraphQL Authentication Mutation

moduleMutationsclassUserSignIn<BaseMutationWithErrors# Define required input argumentsargument:password,String,required:trueargument:username,String,required:true# Define return fieldsfield:token,String,null:truefield:user,Types::UserType,null:truedefresolve(**args)result=Users::SignInService.call(args){errors:result.errors,success:result.success?,token:result.success??result.data[:token]:nil,user:result.success??result.data[:user]:nil}endendend
Enter fullscreen modeExit fullscreen mode

This mutation:

  1. Accepts username and password
  2. Calls the authentication service
  3. Returns token and user data on success
  4. Handles errors gracefully

📧 Email Verification System

Confirmation Service Implementation

moduleUsersclassSendConfirmationEmailService<ApplicationServicedefcallreturnfailure([USER_NOT_FOUND_ERROR])unlessuserreturnfailure([USER_ALREADY_CONFIRMED_ERROR])ifuser.confirmed?send_confirmation_emaillog_event(user:,data:{confirmation_sent:true})success(CONFIRMATION_SENT_MSG)endprivatedefsend_confirmation_email# Generate confirmation email with secure tokenemail=Email.create_confirmation_email!(user:)send_email(email)endendend
Enter fullscreen modeExit fullscreen mode

The confirmation flow:

  1. Checks user existence and confirmation status
  2. Generates a secure confirmation token
  3. Creates and sends confirmation email
  4. Logs the confirmation attempt

Email Token Generation

classEmail<ApplicationRecorddefself.create_confirmation_email!(user:)token=user.generate_token_for(:email_confirmation)create!(to_emails:[user.email],template_id:Rails.application.credentials.dig(:sendgrid,:confirm_template_id),substitutions:[{"confirmation_url":"#{Settings.emails.confirm_url}?token=#{token}",name:user.name}])endend
Enter fullscreen modeExit fullscreen mode

This creates a confirmation email with:

  1. A secure, time-limited token
  2. A personalized confirmation URL
  3. User-specific template data

🔒 Security Implementation

Authentication Middleware

moduleQueriesclassBaseQuery<GraphQL::Schema::Resolverdefauthenticate_user!returnifcurrent_userraiseGraphQL::ExecutionError.new(I18n.t('gql.errors.not_authenticated'),extensions:{code:'AUTHENTICATION_ERROR'})enddefcurrent_usercontext[:current_user]||Current.userendendend
Enter fullscreen modeExit fullscreen mode

This middleware:

  1. Verifies token presence and validity
  2. Maintains user context throughout requests
  3. Handles authentication errors consistently
  4. Provides access to current user data

Password Security

classUser<ApplicationRecord# Regular expression for password validationPASSWORD_FORMAT=/\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\d!@#$%^&*(),.?":{}|<>]{8,72}\z/validates:password,presence:true,length:{minimum:8,maximum:72},format:{with:PASSWORD_FORMAT},if: :password_required?privatedefpassword_required?password_digest.nil?||password.present?endend
Enter fullscreen modeExit fullscreen mode

Password requirements:

  • Minimum 8 characters
  • Maximum 72 characters (bcrypt limitation)
  • Must include lowercase and uppercase letters
  • Must include numbers and special characters
  • Validated only when necessary

🧪 Testing Strategy

RSpec.describeUsers::SignInServicedodescribe'#call'docontext'when credentials are valid'doit'generates an authentication token'doresult=service.callexpect(result.data[:token]).tobe_presentexpect(User.find_by_token_for(:auth_token,result.data[:token])).toeq(user)endit'logs the authentication event'doexpect{service.call}.tochange(AuditLog,:count).by(1)endendcontext'when credentials are invalid'doit'returns appropriate error messages'doresult=described_class.new(invalid_params).callexpect(result.errors).toinclude(I18n.t('services.users.sign_in.user_not_found'))endendendend
Enter fullscreen modeExit fullscreen mode

Our testing approach:

  1. Verifies token generation and validation
  2. Ensures proper error handling
  3. Checks audit logging
  4. Validates security constraints

Conclusion

By implementing these patterns, we've created a secure, maintainable authentication system that:

  • Provides secure token-based authentication
  • Handles email verification properly
  • Maintains high security standards
  • Scales well with application growth

The complete implementation demonstrates how these components work together in a production environment while maintaining security and user experience.


Happy Coding!


Originally published athttps://sulmanweb.com.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Senior Software Engineer with 11 years of expertise in Ruby on Rails and Vue.js, specializing in health, e-commerce, staffing, and transport. Experienced in software development and version analysis.
  • Location
    Multan, Pakistan
  • Education
    MS Software Engineering
  • Work
    Sr. Software Engineer #RubyOnRails #VueJS
  • Joined

More fromSulman Baig

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp