> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/supabase/supabase/llms.txt
> Use this file to discover all available pages before exploring further.

# Sign In Users

> Authenticate users with password, magic links, or OTP codes

Supabase offers multiple sign-in methods to authenticate users. Choose the method that best fits your application's needs.

## Password Sign In

Authenticate users with email and password:

<CodeGroup>
  ```javascript JavaScript theme={null}
  const { data, error } = await supabase.auth.signInWithPassword({
    email: 'example@email.com',
    password: 'example-password',
  })

  if (error) {
    console.error('Error signing in:', error.message)
  } else {
    console.log('User signed in:', data.user)
    console.log('Session:', data.session)
  }
  ```

  ```typescript Next.js Server Action theme={null}
  'use server'

  import { revalidatePath } from 'next/cache'
  import { redirect } from 'next/navigation'
  import { createClient } from '@/lib/supabase/server'

  export async function signIn(formData: FormData) {
    const supabase = await createClient()

    const data = {
      email: formData.get('email') as string,
      password: formData.get('password') as string,
    }

    const { error } = await supabase.auth.signInWithPassword(data)

    if (error) {
      redirect('/error')
    }

    revalidatePath('/', 'layout')
    redirect('/')
  }
  ```

  ```dart Flutter theme={null}
  final AuthResponse res = await supabase.auth.signInWithPassword(
    email: 'example@email.com',
    password: 'example-password',
  );
  final Session? session = res.session;
  final User? user = res.user;
  ```

  ```python Python theme={null}
  data = supabase.auth.sign_in_with_password({
      "email": "example@email.com",
      "password": "example-password"
  })
  print(f"User: {data.user}")
  print(f"Session: {data.session}")
  ```
</CodeGroup>

## Magic Link Sign In

Passwordless authentication via email:

```javascript theme={null}
const { data, error } = await supabase.auth.signInWithOtp({
  email: 'example@email.com',
  options: {
    emailRedirectTo: 'https://example.com/auth/callback',
  },
})

if (error) {
  console.error('Error:', error.message)
} else {
  console.log('Check your email for the magic link!')
}
```

### Complete Magic Link Example

```jsx React Magic Link Component theme={null}
import { useState, useEffect } from 'react'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)

export default function MagicLinkAuth() {
  const [email, setEmail] = useState('')
  const [loading, setLoading] = useState(false)
  const [user, setUser] = useState(null)

  useEffect(() => {
    // Check for existing session
    supabase.auth.getSession().then(({ data: { session } }) => {
      setUser(session?.user ?? null)
    })

    // Listen for auth changes
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_event, session) => {
        setUser(session?.user ?? null)
      }
    )

    return () => subscription.unsubscribe()
  }, [])

  const handleLogin = async (e) => {
    e.preventDefault()
    setLoading(true)

    const { error } = await supabase.auth.signInWithOtp({
      email,
      options: {
        emailRedirectTo: window.location.origin,
      },
    })

    if (error) {
      alert(error.message)
    } else {
      alert('Check your email for the login link!')
    }
    
    setLoading(false)
  }

  const handleLogout = async () => {
    await supabase.auth.signOut()
    setUser(null)
  }

  if (user) {
    return (
      <div>
        <h1>Welcome!</h1>
        <p>You are logged in as: {user.email}</p>
        <button onClick={handleLogout}>Sign Out</button>
      </div>
    )
  }

  return (
    <form onSubmit={handleLogin}>
      <h1>Sign In with Magic Link</h1>
      <input
        type="email"
        placeholder="Your email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        required
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Loading...' : 'Send magic link'}
      </button>
    </form>
  )
}
```

## Phone/SMS Sign In

Authenticate with phone number and OTP:

```javascript theme={null}
// Send OTP
const { data, error } = await supabase.auth.signInWithOtp({
  phone: '+13334445555',
})

// Verify OTP
const { data, error } = await supabase.auth.verifyOtp({
  phone: '+13334445555',
  token: '123456',
  type: 'sms',
})
```

<Warning>
  Phone authentication requires configuring an SMS provider in your Supabase dashboard under Authentication > Settings > Phone Auth.
</Warning>

## Session Management

### Get Current Session

```javascript theme={null}
const { data: { session } } = await supabase.auth.getSession()

if (session) {
  console.log('User is signed in:', session.user)
  console.log('Access token:', session.access_token)
} else {
  console.log('No active session')
}
```

### Get Current User

```javascript theme={null}
const { data: { user } } = await supabase.auth.getUser()

if (user) {
  console.log('User email:', user.email)
  console.log('User metadata:', user.user_metadata)
}
```

### Refresh Session

```javascript theme={null}
const { data, error } = await supabase.auth.refreshSession()
const { session, user } = data
```

## Auth State Changes

Listen for authentication events:

```javascript theme={null}
const { data: { subscription } } = supabase.auth.onAuthStateChange(
  (event, session) => {
    console.log('Auth event:', event)
    
    switch (event) {
      case 'SIGNED_IN':
        console.log('User signed in:', session.user)
        break
      case 'SIGNED_OUT':
        console.log('User signed out')
        break
      case 'TOKEN_REFRESHED':
        console.log('Token refreshed')
        break
      case 'USER_UPDATED':
        console.log('User updated')
        break
    }
  }
)

// Unsubscribe when component unmounts
subscription.unsubscribe()
```

## Sign Out

End the user session:

```javascript theme={null}
const { error } = await supabase.auth.signOut()

if (error) {
  console.error('Error signing out:', error.message)
} else {
  console.log('Signed out successfully')
}
```

### Sign Out from All Devices

```javascript theme={null}
// Sign out from all sessions
const { error } = await supabase.auth.signOut({ scope: 'global' })
```

## Complete Sign-In Form

```jsx React Sign-In Component theme={null}
import { useState } from 'react'
import { createClient } from '@/lib/supabase/client'

export default function SignInForm() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  
  const supabase = createClient()

  const handleSignIn = async (e) => {
    e.preventDefault()
    setLoading(true)
    setError('')

    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    })

    if (error) {
      setError(error.message)
    } else {
      // Redirect or update UI
      window.location.href = '/dashboard'
    }
    
    setLoading(false)
  }

  return (
    <form onSubmit={handleSignIn}>
      <h1>Sign In</h1>
      
      {error && (
        <div style={{ color: 'red', marginBottom: '1rem' }}>
          {error}
        </div>
      )}
      
      <input
        type="email"
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        required
      />
      
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        required
      />
      
      <button type="submit" disabled={loading}>
        {loading ? 'Signing in...' : 'Sign In'}
      </button>
      
      <p>
        Don't have an account? <a href="/signup">Sign up</a>
      </p>
    </form>
  )
}
```

## Password Recovery

Send password reset email:

```javascript theme={null}
const { data, error } = await supabase.auth.resetPasswordForEmail(
  'user@example.com',
  {
    redirectTo: 'https://example.com/update-password',
  }
)
```

Update password:

```javascript theme={null}
const { data, error } = await supabase.auth.updateUser({
  password: 'new-password'
})
```

## Error Handling

Common sign-in errors:

| Error Code            | Description             | Solution                  |
| --------------------- | ----------------------- | ------------------------- |
| `invalid_credentials` | Wrong email or password | Verify credentials        |
| `email_not_confirmed` | Email not verified      | Resend confirmation email |
| `user_not_found`      | User doesn't exist      | Direct to sign up         |
| `invalid_grant`       | Session expired         | Request new magic link    |

## Security Best Practices

<AccordionGroup>
  <Accordion title="Rate Limiting">
    Supabase automatically rate limits sign-in attempts. Configure limits in Authentication > Settings > Rate Limits.
  </Accordion>

  <Accordion title="Session Timeout">
    Sessions expire after 1 hour by default. Supabase automatically refreshes tokens if the user is active.
  </Accordion>

  <Accordion title="Secure Cookies">
    Always use HTTPS in production. Supabase sets secure, httpOnly cookies automatically.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="OAuth Sign In" icon="share-nodes" href="/auth/oauth">
    Add social login providers
  </Card>

  <Card title="Multi-Factor Auth" icon="shield-halved" href="/auth/mfa">
    Enhance security with MFA
  </Card>
</CardGroup>
