Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE OAuth Impl #1048

Merged
merged 3 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/entities/auth/base/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (h *Handler) ProviderCallback(c *fiber.Ctx) error {
return err
}

return c.SendStatus(http.StatusOK)
return c.Status(http.StatusOK).JSON(user)
}

func (h *Handler) ProviderLogout(c *fiber.Ctx) error {
Expand Down
2 changes: 1 addition & 1 deletion backend/integrations/oauth/crypt/crypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func Encrypt(data string, passphrase string) (string, error) {
}

plaintext := []byte(data)
if len(plaintext) > 1028 {
if len(plaintext) > 4096 {
return "", fmt.Errorf("plaintext too long")
}

Expand Down
5 changes: 2 additions & 3 deletions backend/integrations/oauth/soth/sothic/sothic.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ func CompleteUserAuth(c *fiber.Ctx) (soth.User, error) {
}

gu, err := provider.FetchUser(sess)

return gu, err
}

Expand All @@ -227,6 +228,7 @@ func validateState(c *fiber.Ctx, sess soth.Session) error {
}

originalState := authURL.Query().Get("state")

if originalState != "" && (originalState != c.Query("state")) {
return errors.New("state token mismatch")
}
Expand Down Expand Up @@ -357,13 +359,10 @@ func updateSessionValue(session *session.Session, key, value string) error {
if err := gz.Close(); err != nil {
return err
}

encrypted, err := encrypter(b.String())
if err != nil {
return err
}

session.Set(key, encrypted)

return nil
}
8 changes: 4 additions & 4 deletions backend/middleware/auth/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ func (m *AuthMiddlewareHandler) UserAuthorizeById(c *fiber.Ctx) error {
return c.SendStatus(http.StatusUnauthorized)
}

user := models.UnmarshalUser(strUser)
user := *models.UnmarshalUser(strUser)

if user.Role == models.Super {
locals.SetUser(c, user)
locals.SetUser(c, &user)
return c.Next()
}

Expand All @@ -29,8 +29,8 @@ func (m *AuthMiddlewareHandler) UserAuthorizeById(c *fiber.Ctx) error {
return err
}

if idAsUUID == &user.ID {
locals.SetUser(c, user)
if *idAsUUID == user.ID {
locals.SetUser(c, &user)
return c.Next()
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@generatesac/lib",
"version": "0.0.171",
"version": "0.0.179",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
77 changes: 25 additions & 52 deletions frontend/lib/src/api/authApi.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,42 @@
import { LoginRequestBody, RefreshTokenRequestBody } from "../types/auth";
import { User, userSchema } from "../types/user";
import {
EmailRequestBody,
VerifyEmailRequestBody,
VerifyPasswordResetTokenRequestBody,
} from "../types/verification";
import { baseApi } from "./base";
import { User, userSchema } from "../types";
import { LoginResponse, OAuthCallbackRequestQueryParams } from "../types/auth";
import { baseApi, handleQueryParams } from "./base";

const AUTH_API_BASE_URL = "/auth";
const PROVIDER = "microsoftonline";

export const authApi = baseApi.injectEndpoints({
endpoints: (builder) => ({
login: builder.mutation<User, LoginRequestBody>({
query: (body) => ({
login: builder.query<LoginResponse, void>({
query: () => ({
url: `${AUTH_API_BASE_URL}/login`,
method: "POST",
body,
method: "GET",
responseHandler: 'text',
}),
transformResponse: (response: User) => {
return userSchema.parse(response);
transformResponse: async (_, meta) => {
const redirectUri = meta?.response?.headers.get("Redirect") as string;
const sac_session = meta?.response?.headers.get("_sac_session") as string;

return {
redirect_uri: redirectUri,
sac_session,
}
},
}),
logout: builder.mutation<void, void>({
logout: builder.query<void, void>({
query: () => ({
url: `${AUTH_API_BASE_URL}/logout`,
method: "POST",
}),
}),
refresh: builder.mutation<void, RefreshTokenRequestBody>({
query: (body) => ({
url: "refresh",
method: "POST",
body,
}),
}),
forgotPassword: builder.mutation<void, EmailRequestBody>({
query: (body) => ({
url: `${AUTH_API_BASE_URL}/forgot-password`,
method: "POST",
body,
}),
}),
verifyPasswordResetToken: builder.mutation<
void,
VerifyPasswordResetTokenRequestBody
>({
query: (body) => ({
url: `${AUTH_API_BASE_URL}/verify-reset`,
method: "POST",
body,
method: "GET",
}),
}),
sendCode: builder.mutation<void, EmailRequestBody>({
query: (body) => ({
url: `${AUTH_API_BASE_URL}/send-code`,
method: "POST",
body,
}),
}),
verifyEmail: builder.mutation<void, VerifyEmailRequestBody>({
query: (body) => ({
url: `${AUTH_API_BASE_URL}/verify-email`,
method: "POST",
body,
callback: builder.query<User, OAuthCallbackRequestQueryParams>({
query: (params) => ({
url: handleQueryParams(`${AUTH_API_BASE_URL}/${PROVIDER}/callback`, params),
method: "GET",
}),
transformResponse: (response) => {
return userSchema.parse(response);
}
}),
}),
});
2 changes: 1 addition & 1 deletion frontend/lib/src/api/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const baseApi = createApi({
// User slice existing must exist in all dependent apps:
const token = (getState() as { user: { accessToken: string } })?.user?.accessToken;
if (token) {
headers.set("Authorization", `Bearer ${token}`);
headers.set("_sac_session", token);
}
return headers;
},
Expand Down
11 changes: 0 additions & 11 deletions frontend/lib/src/api/userApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { z } from "zod";

import { UpdatePasswordRequestBody } from "../types/auth";
import { Club, clubSchema } from "../types/club";
import { PaginationQueryParams } from "../types/root";
import { Tag, tagSchema } from "../types/tag";
Expand Down Expand Up @@ -82,16 +81,6 @@ export const userApi = baseApi.injectEndpoints({
}),
invalidatesTags: (_result, _, id) => [{ type: "User", id }],
}),
updatePassword: builder.mutation<
void,
{ id: string; body: UpdatePasswordRequestBody }
>({
query: ({ id, body }) => ({
url: `${USER_API_BASE_URL}/${id}/password`,
method: "PATCH",
body,
}),
}),
userFollowing: builder.query<Club[], string>({
query: (id) => ({
url: `${USER_API_BASE_URL}/${id}/follower/`,
Expand Down
33 changes: 9 additions & 24 deletions frontend/lib/src/types/auth.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import { z } from "zod";

// Schemas:
export const loginRequestBodySchema = z.object({
email: z.string().email(),
password: z.string().min(8),
export const loginResponseSchema = z.object({
redirect_uri: z.string(),
sac_session: z.string(),
});

export const updatePasswordRequestBodySchema = z.object({
old_password: z.string().min(8),
new_password: z.string().min(8),
});

export const refreshTokenRequestBodySchema = z.object({
refresh_token: z.string(),
});

export const tokensSchema = z.object({
access_token: z.string(),
refresh_token: z.string(),
export const oauthCallbackRequestQueryParams = z.object({
code: z.string(),
session_state: z.string(),
state: z.string(),
});

// Types:
export type LoginRequestBody = z.infer<typeof loginRequestBodySchema>;
export type UpdatePasswordRequestBody = z.infer<
typeof updatePasswordRequestBodySchema
>;
export type RefreshTokenRequestBody = z.infer<
typeof refreshTokenRequestBodySchema
>;
export type Tokens = z.infer<typeof tokensSchema>;
export type LoginResponse = z.infer<typeof loginResponseSchema>;
export type OAuthCallbackRequestQueryParams = z.infer<typeof oauthCallbackRequestQueryParams>;
8 changes: 4 additions & 4 deletions frontend/lib/src/types/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { rootModelSchema } from "./root";
export const userRoleEnum = z.enum(["super", "student"]);

export const collegeEnum = z.enum([
"",
"CAMD",
"DMSB",
"KCCS",
Expand All @@ -18,6 +19,7 @@ export const collegeEnum = z.enum([
]);

export const majorEnum = z.enum([
"",
"africanaStudies",
"americanSignLanguage",
"americanSignLanguage-EnglishInterpreting",
Expand Down Expand Up @@ -120,7 +122,7 @@ export const majorEnum = z.enum([
"theatre",
]);

export const graduationCycleEnum = z.enum(["december", "may"]);
export const graduationCycleEnum = z.enum(["december", "may", ""]);

export const yearEnum = z.enum(["1", "2", "3", "4", "5"]);

Expand Down Expand Up @@ -155,16 +157,14 @@ export const createUserTagsRequestBodySchema = z.object({

const userSchemaIntermediate = z.object({
role: userRoleEnum,
first_name: z.string().min(1),
last_name: z.string().min(1),
name: z.string().min(1),
email: z.string().email(),
major0: majorEnum.optional(),
major1: majorEnum.optional(),
major2: majorEnum.optional(),
college: collegeEnum.optional(),
graduation_cycle: graduationCycleEnum.optional(),
graduation_year: z.number().optional(),
is_verified: z.boolean(),
});

export const userSchema = userSchemaIntermediate.merge(rootModelSchema);
Expand Down
2 changes: 1 addition & 1 deletion frontend/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@fortawesome/react-native-fontawesome": "^0.3.2",
"@generatesac/lib": "0.0.171",
"@generatesac/lib": "0.0.179",
"@gorhom/bottom-sheet": "^4.6.3",
"@hookform/resolvers": "^3.4.2",
"@react-native-async-storage/async-storage": "^1.23.1",
Expand Down
Loading
Loading