|
| 1 | +import { Tab, Tabs } from "rspress/theme"; |
| 2 | + |
| 3 | +# Auth and Social Login |
| 4 | + |
| 5 | +Authentication is a critical component of modern web applications, yet implementing it correctly can be challenging and error-prone. AIScript simplifies this process with built-in authentication directives that handle complex security flows while maintaining type safety throughout the authentication process. |
| 6 | + |
| 7 | +## Authentication Options |
| 8 | + |
| 9 | +AIScript provides several authentication mechanisms out of the box: |
| 10 | + |
| 11 | +- **JWT Authentication**: Secure token-based authentication |
| 12 | +- **Basic Authentication**: Simple username/password authentication |
| 13 | +- **SSO (Single Sign-On)**: Integration with social login providers like Google, GitHub, and more |
| 14 | + |
| 15 | +## JWT |
| 16 | + |
| 17 | +JSON Web Tokens (JWT) provide a stateless authentication mechanism that's perfect for APIs and single-page applications. AIScript makes JWT implementation straightforward with the `@auth` directive. |
| 18 | + |
| 19 | +<Tabs> |
| 20 | +<Tab label="route.ai"> |
| 21 | + |
| 22 | +```js |
| 23 | +post /signin { |
| 24 | + body { |
| 25 | + username: str |
| 26 | + password: str |
| 27 | + } |
| 28 | + |
| 29 | + // Verify username and password correctly |
| 30 | + use std.auth.jwt; |
| 31 | + // Create payload with claims |
| 32 | + let payload = { |
| 33 | + sub: body.username, |
| 34 | + }; |
| 35 | + |
| 36 | + // Create access token that expires in 1 hour (3600 seconds) |
| 37 | + let token = jwt.create_access_token(payload, 3600, "your-secret"); |
| 38 | + return { token }; |
| 39 | +} |
| 40 | + |
| 41 | +@auth |
| 42 | +get /ask { |
| 43 | + query { |
| 44 | + @string(min_len=5, max_len=50) |
| 45 | + question: str |
| 46 | + } |
| 47 | + |
| 48 | + ai fn ask_llm(question: str) -> str { |
| 49 | + return prompt question; |
| 50 | + } |
| 51 | + let answer = ask_llm(query.question); |
| 52 | + return { answer }; |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +</Tab> |
| 57 | +<Tab label="curl"> |
| 58 | + |
| 59 | +```bash |
| 60 | +$ curl --location 'http://localhost:8080/signin' \ |
| 61 | +--header 'Content-Type: application/json' \ |
| 62 | +--data '{"username": "abc", "password": "123455"}' |
| 63 | + |
| 64 | +{ |
| 65 | + "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhYmMiLCJleHAiOjE3NDEzMjA0NzUsIm5iZiI6MTc0MTMxNjg3NSwiaWF0IjoxNzQxMzE2ODc1fQ.542CSBvnWbmQZAO8Ba-IjxxsZ4U-JSTmSalJFN574SY" |
| 66 | +} |
| 67 | + |
| 68 | +$ curl --location --request GET 'http://localhost:8080/ask?question=What%20is%20the%20capital%20of%20China%3F' \ |
| 69 | +--header 'Content-Type: application/json' \ |
| 70 | +--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhYmMiLCJleHAiOjE3NDEzMjA0NzUsIm5iZiI6MTc0MTMxNjg3NSwiaWF0IjoxNzQxMzE2ODc1fQ.542CSBvnWbmQZAO8Ba-IjxxsZ4U-JSTmSalJFN574SY' |
| 71 | + |
| 72 | +{ |
| 73 | + "answer": "The capital of France is Paris." |
| 74 | +} |
| 75 | +``` |
| 76 | +</Tab> |
| 77 | +<Tab label="project.toml"> |
| 78 | + |
| 79 | +```toml |
| 80 | +[auth.jwt] |
| 81 | +secret = "your-secret" |
| 82 | +expiration = 3600 # Token expiration time in seconds |
| 83 | +``` |
| 84 | + |
| 85 | +</Tab> |
| 86 | +</Tabs> |
| 87 | + |
| 88 | +When a route is decorated with `@auth`, AIScript automatically: |
| 89 | + |
| 90 | +1. Verifies the JWT token from the `Authorization` header |
| 91 | +2. Rejects requests with invalid or expired tokens |
| 92 | +3. Makes the decoded token payload available within the route handler |
| 93 | + |
| 94 | +Configure JWT settings in your `project.toml`: |
| 95 | + |
| 96 | +```toml |
| 97 | +[auth.jwt] |
| 98 | +secret = "your-secret" |
| 99 | +expiration = 3600 # Token expiration time in seconds |
| 100 | +``` |
| 101 | + |
| 102 | +For enhanced security, use environment variables for sensitive values like the JWT secret. |
| 103 | + |
| 104 | +## Basic Auth |
| 105 | + |
| 106 | +For simpler use cases or admin interfaces, AIScript provides basic authentication with the `@basic_auth` directive: |
| 107 | + |
| 108 | +```js |
| 109 | +@basic_auth |
| 110 | +post /guess { |
| 111 | + body { |
| 112 | + @number(min=1, max=100) |
| 113 | + magic: int = 1 |
| 114 | + } |
| 115 | + |
| 116 | + let result = "Try again!"; |
| 117 | + if body.magic == 42 { |
| 118 | + result = "You guessed it!"; |
| 119 | + } |
| 120 | + return { result }; |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | +The `@basic_auth` directive validates username and password credentials according to your configuration. |
| 125 | + |
| 126 | +Configure basic authentication in your `project.toml`: |
| 127 | + |
| 128 | +```toml |
| 129 | +[auth.basic] |
| 130 | +username = "admin" |
| 131 | +password = "123456" # Use environment variables for production |
| 132 | +``` |
| 133 | + |
| 134 | +## Social Login with SSO |
| 135 | + |
| 136 | +AIScript makes implementing social login seamless with the `@sso` directive. This handles the complex OAuth flows required by providers like Google, GitHub, or Microsoft. |
| 137 | + |
| 138 | +### Setting Up Google Authentication |
| 139 | + |
| 140 | +1. Configure the provider in your `project.toml`: |
| 141 | + |
| 142 | +```toml |
| 143 | +[sso.google] |
| 144 | +client_id = "123" # Your Google OAuth client ID |
| 145 | +client_secret = "abc" # Your Google OAuth client secret |
| 146 | +redirect_url = "http://localhost:8080/auth/google/callback" |
| 147 | +scopes = ["email", "profile"] |
| 148 | +``` |
| 149 | + |
| 150 | +2. Create an authorization endpoint: |
| 151 | + |
| 152 | +```js |
| 153 | +@sso(provider="google") |
| 154 | +get /auth/google { |
| 155 | + let url = sso.authority_url(); |
| 156 | + print(url); |
| 157 | + return temporary_redirect(target=url); |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +3. Implement the callback endpoint: |
| 162 | + |
| 163 | +```js |
| 164 | +@sso(provider="google") |
| 165 | +get /auth/google/callback { |
| 166 | + query { |
| 167 | + code: str, |
| 168 | + state: str, |
| 169 | + } |
| 170 | + |
| 171 | + print("code", query.code); |
| 172 | + print("state", query.state); |
| 173 | + let user_info = sso.verify(code=query.code); |
| 174 | + print(user_info); |
| 175 | + return { user_info }; |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +When a user visits `/auth/google`, they'll be redirected to Google's authentication page. After successful authentication, Google redirects back to your `/auth/google/callback` endpoint with an authorization code. The `sso.verify()` function exchanges this code for an access token and retrieves the user's profile information. |
| 180 | + |
| 181 | +### Supporting Multiple Providers |
| 182 | + |
| 183 | +AIScript supports multiple SSO providers simultaneously. Simply add additional configurations in your `project.toml`: |
| 184 | + |
| 185 | +```toml |
| 186 | +[sso.github] |
| 187 | +client_id = "456" |
| 188 | +client_secret = "def" |
| 189 | +redirect_url = "http://localhost:8080/auth/github/callback" |
| 190 | +scopes = ["user:email"] |
| 191 | + |
| 192 | +[sso.microsoft] |
| 193 | +client_id = "789" |
| 194 | +client_secret = "ghi" |
| 195 | +redirect_url = "http://localhost:8080/auth/microsoft/callback" |
| 196 | +scopes = ["User.Read"] |
| 197 | +``` |
| 198 | + |
| 199 | +Then create corresponding route handlers for each provider: |
| 200 | + |
| 201 | +```js |
| 202 | +@sso(provider="github") |
| 203 | +get /auth/github { |
| 204 | + return temporary_redirect(target=sso.authority_url()); |
| 205 | +} |
| 206 | + |
| 207 | +@sso(provider="github") |
| 208 | +get /auth/github/callback { |
| 209 | + query { code: str, state: str } |
| 210 | + let user_info = sso.verify(code=query.code); |
| 211 | + return { user_info }; |
| 212 | +} |
| 213 | +``` |
| 214 | + |
| 215 | +## Conclusion |
| 216 | + |
| 217 | +AIScript's authentication directives simplify the implementation of secure authentication flows without sacrificing flexibility. Whether you need simple password-based authentication or complex multi-provider SSO, AIScript provides the tools to implement authentication with minimal boilerplate while maintaining type safety throughout the process. |
| 218 | + |
| 219 | +By abstracting away the complex security details, AIScript lets you focus on building your application logic while ensuring your authentication implementation follows security best practices. |
0 commit comments