Securely Managing API Keys - Next.js vs. Angular

Image ...

When building modern web applications, securely managing sensitive information like API keys is a critical concern. This question recently came up while I was working on a project integrating OpenAI's API, where protecting the API key was crucial to prevent unauthorized usage and potential cost implications. Whether you're using React, Next.js, or Angular, the handling of API keys requires thoughtful implementation to prevent them from being exposed to the client-side or intercepted by malicious actors. This article shows the different approaches for each technology, highlighting how to keep your keys secure.

Next.js API Key Management

Next.js, a React framework, provides built-in server-side capabilities that simplify secure API key handling. You can use API keys safely in three main ways:

1. API Routes

The /api/route.ts files run exclusively on the server, making them perfect for secure API key usage:

export default async function handler(req, res) {
  const apiKey = process.env.API_KEY;
  const response = await fetch("https://example.com/api", {
    headers: { Authorization: `Bearer ${apiKey}` },
  });

  const data = await response.json();
  res.status(200).json(data);
}

2. Server-Side Props

export async function getServerSideProps() {
  const apiKey = process.env.API_KEY;
  const data = await fetchSecureData(apiKey);

  return {
    props: { data },
  };
}

3. Static Props (Build-time)

export async function getStaticProps() {
  const apiKey = process.env.API_KEY;
  const data = await fetchSecureData(apiKey);

  return {
    props: { data },
  };
}

Angular API Key Management

Angular now offers two approaches to API key security, depending on whether you're using Server-Side Rendering (SSR) or not.

With Angular Universal (SSR)

Angular Universal allows you to handle API keys securely on the server side, similar to Next.js:

// server.ts
app.get("/api/data", (req, res) => {
  const apiKey = process.env.API_KEY;
  // Make secure API calls here
});

// component.ts
@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}

  getData() {
    return this.http.get("/api/data");
  }
}

Without SSR

For client-side only applications, you'll need to implement one of these approaches:

  1. Backend Proxy (Recommended): Create a dedicated backend service to handle sensitive API calls:
// proxy.service.ts
@Injectable()
export class ProxyService {
  constructor(private http: HttpClient) {}

  getData() {
    return this.http.get("/api/proxy-endpoint");
  }
}
  1. Environment Configuration (Public Keys Only): Only use environment files for public keys that are safe to expose:
// environment.ts
export const environment = {
  production: false,
  publicApiKey: "your-public-key",
};

Security Best Practices

  1. Environment Variables:

    • Store API keys in .env files
    • Never commit .env files to version control
    • Use .env.example for documentation
    • Configure environment variables in your hosting platform
  2. HTTPS and Access Control:

    • Always use HTTPS for data transmission
    • Restrict API key usage by domain/IP where possible
    • Implement proper CORS policies
  3. Framework-Specific Considerations:

    • Next.js: Only prefix environment variables with NEXT_PUBLIC_ if they're meant to be public
    • Angular: Keep sensitive environment variables in server-side code only
  4. Deployment:

    • Use hosting platforms' secret management systems (Vercel, AWS, Azure, etc.)
    • Regularly rotate API keys
    • Monitor API usage for suspicious patterns

Conclusion

Both Next.js and Angular provide robust ways to handle API keys securely. Next.js offers built-in server-side capabilities that make secure implementation straightforward, while Angular with Universal now provides similar server-side security features. For client-side only Angular applications, using a backend proxy remains the most secure approach.

Remember to regularly audit your security practices and keep your dependencies updated to maintain strong application security.

Useful links

Next.js:

Environment Variables: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
API Routes Security: https://nextjs.org/docs/app/building-your-application/routing/route-handlers#request-helpers

Angular:

Security best practices: https://angular.dev/best-practices/security
Server-side rendering: https://angular.dev/guide/ssr